博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法导论 O(n)时间内反转单链表
阅读量:4088 次
发布时间:2019-05-25

本文共 6249 字,大约阅读时间需要 20 分钟。

算法导论 O(n)时间内反转单链表

1. 算法导论原题

Give a O(n) time nonrecursive procedure that reverses a singly linked list of n elements. The procedure should use no more than constant storage beyond that needed for thelist itself.

译:实现一个时间复杂度为O(n)的非递归过程反转一个有n个元素的单链表。这个过程应该使用常量的储存空间(除了链表本身)。

2. 如何在O(n)时间内反转单链表?

由于是单链表,想要在O(n)时间内反转单链表,就不可能遍历整个链表到后面的结点来跟前面结点交换数据。因此我们能做的,就是改变链表每一个结点的指针指向为前一个结点。我们需要用三个结点的储存空间:上一个结点、当前结点、下一个结点。首先将当前结点的下一个结点保存(因为下一步要改变当前结点的下一个结点),然后将当前结点指向上一个结点,再将当前结点保存到上一个结点,最后将当前结点移动到刚刚保存的下一个结点。题目没有说是用循环单链表,但是循环单链表和普通单链表它们的存储空间和O(n)时间内反转实现原理是一样的,所以我这里直接用循环单链表就行了。

3. 主要代码实现(C++)

template
bool CircularSinglyLink
::Reverse(){ Node
* pPrevNode = m_pHeadNode; Node
* pCurrentNode = m_pHeadNode->GetNext(); while(pCurrentNode != m_pHeadNode) { Node
* nextNode = pCurrentNode->GetNext(); pCurrentNode->SetNext(pPrevNode); pPrevNode = pCurrentNode; pCurrentNode = nextNode; } m_pHeadNode->SetNext(pPrevNode); return true;}

4. 完整代码实现(C++)

//CircularSinglyLink.h#pragma once#include 
#include
template
class Node{public: Node(Node
* pNext = NULL, ElemType* pData = NULL); ElemType const& GetData() const; void SetData(ElemType val) ; Node
* const& GetNext() const; void SetNext(Node
* val);private: ElemType* m_pData; Node
* m_pNext;};template
class CircularSinglyLink{public: CircularSinglyLink(); unsigned int const& GetLength() const; bool Insert(ElemType elem, unsigned int pos); bool InsertByPosNode(ElemType elem, Node
* posNode, Node
** RetInsetNode = NULL); bool Delete(unsigned int pos, ElemType* elem); bool Search(unsigned int pos, ElemType* elem) const; bool Visit(ElemType* elem, const unsigned int& pos) const; bool Empty(); Node
* HavaHeadNode(); bool Reverse();private: Node
* m_pHeadNode; unsigned int m_length;};//————————————————————————————————//Node类的实现template
Node
::Node(Node
* pNext /*= NULL*/, ElemType* pData /*= NULL*/) :m_pNext(pNext),m_pData(pData){}template
void Node
::SetNext(Node
* val){ m_pNext = val;}template
Node
* const& Node
::GetNext() const{ return m_pNext;}template
void Node
::SetData(ElemType val){ m_pData = val;}template
ElemType const& Node
::GetData() const{ return *m_pData;}//————————————————————————————————//CircularSinglyLink类实现template
CircularSinglyLink
::CircularSinglyLink() :m_pHeadNode(new Node
()),m_length(0){ m_pHeadNode->SetNext(m_pHeadNode);}template
bool CircularSinglyLink
::InsertByPosNode(ElemType elem, Node
* posNode, Node
** RetInsetNode /*= NULL*/){ Node
* insertNode = new Node
(posNode->GetNext(),new ElemType(elem)); posNode->SetNext(insertNode); ++m_length; *RetInsetNode = insertNode; return true;}template
bool CircularSinglyLink
::Insert(ElemType elem, unsigned int pos){ if (pos > GetLength() || pos < 0) { assert(false && "Error: SinglyLink's insert pos is out of range!\n"); return false; } for(Node
* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0) { Node
* insertNode = new Node
(pCurrentNode->GetNext(),new ElemType(elem)); pCurrentNode->SetNext(insertNode); ++m_length; return true; } } assert(false && "Error: SinglyLink Insert failed for unknow reason!"); return false;}template
bool CircularSinglyLink
::Delete(unsigned int pos, ElemType* elem){ if (pos >= GetLength() || pos < 0) { assert(false && "Error: SinglyLink's delete pos is out of range!\n"); } for(Node
* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0) { Node
* deleteNode = pCurrentNode->GetNext(); pCurrentNode->SetNext(deleteNode->GetNext()); *elem = deleteNode->GetData(); delete deleteNode; --m_length; return true; } } assert(false && "Error: SinglyLink pos delete failed for unknow reason!"); return false;}template
unsigned int const& CircularSinglyLink
::GetLength() const{ return m_length;}template
bool CircularSinglyLink
::Search(unsigned int pos, ElemType* elem) const{ if (pos >= GetLength() || pos < 0) { assert(false && "Error: SinglyLink's search pos is out of range!\n"); } for(Node
* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0 && (pCurrentNode->GetNext() != NULL) ) { *elem = pCurrentNode->GetNext()->GetData(); return true; } } return false;}template
bool CircularSinglyLink
::Visit(ElemType* elem, const unsigned int& pos) const{ if (pos >= GetLength() || pos < 0) { return false; } return Search(pos,elem);}template
bool CircularSinglyLink
::Empty(){ return !m_length;}template
Node
* CircularSinglyLink
::HavaHeadNode(){ return m_pHeadNode;}template
bool CircularSinglyLink
::Reverse(){ Node
* pPrevNode = m_pHeadNode; Node
* pCurrentNode = m_pHeadNode->GetNext(); while(pCurrentNode != m_pHeadNode) { Node
* nextNode = pCurrentNode->GetNext(); pCurrentNode->SetNext(pPrevNode); pPrevNode = pCurrentNode; pCurrentNode = nextNode; } m_pHeadNode->SetNext(pPrevNode); return true;}
//Util.h#pragma oncenamespace Util{    template
void PrintMemory(const T& dateStruct, unsigned int size) { cout << "PrintMemory: "; for (int i = 0; i != size; i++) { ElemType tempElem; if (!dateStruct.Visit(&tempElem,i)) { printf("\n"); return; } printf("%d ",tempElem); } printf("\n"); }}
//main.cpp#include "Util.h"#include "CircularSinglyLink.h"#include 
using namespace std;typedef int ElemType;int main(){ CircularSinglyLink
testCircularSinglyLink; for (int i = 0; i != 5; i++) { testCircularSinglyLink.Insert(i+1,i); } cout << "testCircularSinglyLink:\n"; Util::PrintMemory(testCircularSinglyLink,testCircularSinglyLink.GetLength()); cout << "\nReverse testCircularSinglyLink...\n"; testCircularSinglyLink.Reverse(); cout << "\ntestCircularSinglyLink:\n"; Util::PrintMemory(testCircularSinglyLink,testCircularSinglyLink.GetLength()); return 0;}

5. 程序运行结果

testCircularSinglyLink:

PrintMemory: 1 2 3 4 5

Reverse testCircularSinglyLink…

testCircularSinglyLink:

PrintMemory: 5 4 3 2 1

转载地址:http://ziyii.baihongyu.com/

你可能感兴趣的文章
(python版) Leetcode-66.加一
查看>>
(python版) Leetcode-287. 寻找重复数
查看>>
(python版) Leetcode-566. 重塑矩阵
查看>>
(python版) Leetcode-485. 最大连续1的个数
查看>>
(python版) Leetcode-189. 旋转数组
查看>>
四两拨千斤!深度主动学习综述2020
查看>>
了解DeepFakes背后的技术
查看>>
VSCode cv2 PyTorch 的红色波浪线【2020年解决方案】
查看>>
记【安装mmcv教程】 以及 遇到的Error
查看>>
深度解读AI从业者必备算法和工具 -- 公开课
查看>>
深度学习换脸发展调研-Deepfake
查看>>
《剑指Offer》JZ3:从尾到头打印链表
查看>>
《剑指Offer》JZ14:输出链表中倒数第k个结点
查看>>
《剑指Offer》JZ15:反转链表(双解法)
查看>>
《剑指Offer》JZ16:合并两个排序的链表(迭代法)
查看>>
(python版)《剑指Offer》JZ25:复杂链表的复制(详解)
查看>>
(python版)《剑指Offer》JZ36:两个链表的第一个公共结点
查看>>
(python版)《剑指Offer》JZ55:链表中环的入口结点
查看>>
(python版)《剑指Offer》JZ4:重建二叉树
查看>>
(python版)《剑指Offer》JZ17:树的子结构
查看>>