算法导论 O(n)时间内反转单链表
来源:互联网 发布:少数民族人脸数据库 编辑:程序博客网 时间:2024/05/19 03:18
算法导论 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<typename ElemType>bool CircularSinglyLink<ElemType>::Reverse(){ Node<ElemType>* pPrevNode = m_pHeadNode; Node<ElemType>* pCurrentNode = m_pHeadNode->GetNext(); while(pCurrentNode != m_pHeadNode) { Node<ElemType>* nextNode = pCurrentNode->GetNext(); pCurrentNode->SetNext(pPrevNode); pPrevNode = pCurrentNode; pCurrentNode = nextNode; } m_pHeadNode->SetNext(pPrevNode); return true;}
4. 完整代码实现(C++)
//CircularSinglyLink.h#pragma once#include <assert.h>#include <stdio.h>template<typename ElemType>class Node{public: Node(Node<ElemType>* pNext = NULL, ElemType* pData = NULL); ElemType const& GetData() const; void SetData(ElemType val) ; Node<ElemType>* const& GetNext() const; void SetNext(Node<ElemType>* val);private: ElemType* m_pData; Node<ElemType>* m_pNext;};template<typename ElemType>class CircularSinglyLink{public: CircularSinglyLink(); unsigned int const& GetLength() const; bool Insert(ElemType elem, unsigned int pos); bool InsertByPosNode(ElemType elem, Node<ElemType>* posNode, Node<ElemType>** 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<ElemType>* HavaHeadNode(); bool Reverse();private: Node<ElemType>* m_pHeadNode; unsigned int m_length;};//————————————————————————————————//Node类的实现template<typename ElemType>Node<ElemType>::Node(Node<ElemType>* pNext /*= NULL*/, ElemType* pData /*= NULL*/) :m_pNext(pNext),m_pData(pData){}template<typename ElemType>void Node<ElemType>::SetNext(Node<ElemType>* val){ m_pNext = val;}template<typename ElemType>Node<ElemType>* const& Node<ElemType>::GetNext() const{ return m_pNext;}template<typename ElemType>void Node<ElemType>::SetData(ElemType val){ m_pData = val;}template<typename ElemType>ElemType const& Node<ElemType>::GetData() const{ return *m_pData;}//————————————————————————————————//CircularSinglyLink类实现template<typename ElemType>CircularSinglyLink<ElemType>::CircularSinglyLink() :m_pHeadNode(new Node<ElemType>()),m_length(0){ m_pHeadNode->SetNext(m_pHeadNode);}template<typename ElemType>bool CircularSinglyLink<ElemType>::InsertByPosNode(ElemType elem, Node<ElemType>* posNode, Node<ElemType>** RetInsetNode /*= NULL*/){ Node<ElemType>* insertNode = new Node<ElemType>(posNode->GetNext(),new ElemType(elem)); posNode->SetNext(insertNode); ++m_length; *RetInsetNode = insertNode; return true;}template<typename ElemType>bool CircularSinglyLink<ElemType>::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<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0) { Node<ElemType>* insertNode = new Node<ElemType>(pCurrentNode->GetNext(),new ElemType(elem)); pCurrentNode->SetNext(insertNode); ++m_length; return true; } } assert(false && "Error: SinglyLink Insert failed for unknow reason!"); return false;}template<typename ElemType>bool CircularSinglyLink<ElemType>::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<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0) { Node<ElemType>* 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<typename ElemType>unsigned int const& CircularSinglyLink<ElemType>::GetLength() const{ return m_length;}template<typename ElemType>bool CircularSinglyLink<ElemType>::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<ElemType>* pCurrentNode = m_pHeadNode; pCurrentNode != NULL; pCurrentNode = pCurrentNode->GetNext()) { if (pos-- == 0 && (pCurrentNode->GetNext() != NULL) ) { *elem = pCurrentNode->GetNext()->GetData(); return true; } } return false;}template<typename ElemType>bool CircularSinglyLink<ElemType>::Visit(ElemType* elem, const unsigned int& pos) const{ if (pos >= GetLength() || pos < 0) { return false; } return Search(pos,elem);}template<typename ElemType>bool CircularSinglyLink<ElemType>::Empty(){ return !m_length;}template<typename ElemType>Node<ElemType>* CircularSinglyLink<ElemType>::HavaHeadNode(){ return m_pHeadNode;}template<typename ElemType>bool CircularSinglyLink<ElemType>::Reverse(){ Node<ElemType>* pPrevNode = m_pHeadNode; Node<ElemType>* pCurrentNode = m_pHeadNode->GetNext(); while(pCurrentNode != m_pHeadNode) { Node<ElemType>* nextNode = pCurrentNode->GetNext(); pCurrentNode->SetNext(pPrevNode); pPrevNode = pCurrentNode; pCurrentNode = nextNode; } m_pHeadNode->SetNext(pPrevNode); return true;}
//Util.h#pragma oncenamespace Util{ template<typename T> 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 <iostream>using namespace std;typedef int ElemType;int main(){ CircularSinglyLink<int> 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 5Reverse testCircularSinglyLink…
testCircularSinglyLink:
PrintMemory: 5 4 3 2 1
0 0
- 算法导论 O(n)时间内反转单链表
- 算法导论8.3-4 O(n)时间内对[0..n^-1]之间的n个数排序
- 算法导论8.3-4 O(n)时间内对[0..n^-1]之间的n个数排序 .
- 算法导论8.3-4 O(n)时间内对[0..n^-1]之间的n个数排序
- 算法导论8.3-4 O(n)时间内对[0..n^-1]之间的n个数排序
- 时间复杂度为O(n)的非递归单链表反转【算法导论课后题】
- 算法导论第9章(o(3n/2)时间内找出最大最小值)
- 算法导论-16.2-6 在O(n)时间内求解分数背包问题
- 单链表反转O(N)
- 设计算法,在O(n)时间内求解分数背包问题
- Manacher算法: 最长回文子串O(N)时间内求解
- 《算法导论》线性时间O(n)排序
- 算法导论 10-2-7 时间为n的非递归过程,反转单链表
- 浅谈manacher算法-O(n)时间内寻找最大回文子串
- 算法导论 10-4-5 O(n)时间 O(1)空间遍历树
- 【链表】非递归过程以O(N)反转单链表
- 【算法导论学习-21】单链表(single linked)的反转
- 算法导论学习 之 顺序统计量的O(n)算法
- 耳机标准
- 韩顺平 java 第八讲第九讲 this、类变量、类方法、封装
- CSS3文本溢出
- Android 蓝牙开发小结与探讨
- Windows2008 Server 常规设置及基本安全策略
- 算法导论 O(n)时间内反转单链表
- Two Sum
- java.sql.SQLException: Lock wait timeout exceeded;
- Jbrowse中的BigWig Tracks配置
- iOS 进阶面试题-Block部分
- 浅析多线程及用法(实例)
- CString string CStringA CStringW string wstring 等字符串转换汇总
- 类似微博快速操作弹出界面
- 汇编语言第二版-第一章