博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
算法导论 使用单链表实现队列
阅读量:4089 次
发布时间:2019-05-25

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

使用单链表实现队列

1. 算法导论原题

10.2-3

Implement a queue by a singly linked list L. The operations ENQUEUE and DEQUEUE should still take O(1) time.
译:使用一个单链表实现一个队列。入队和出队的时间复杂度都应该是O(1)。

2. 使用单链表实现队列

我们假设链表是用头插法,那么1、2、3插进入链表,在链表中的顺序就变成了3、2、1。如果我们想出队,就必须找到链表尾元素出队。因为要保持出队的时间复杂度是O(1),那么插入操作后要保存第一次插入的结点,出队就可以直接将保存的插入后的结点出队即可,然后出队后还要找到第一次插入的结点的前一个结点,又因为这是单链表,需要遍历整个链表才能找到前一个结点,这显然是违反了时间复杂度为O(1)。

假设链表用尾插法,那么1、2、3插进链表,在链表中的顺序依然是1、2、3、如果我们想出队,只需要将头节点的下一个元素出队。为了保持插入的时间复杂度是O(1),不可能每次插入的时候都去遍历链表,因此需要保存插入后的新节点,插入的操作就在保存的新节点后面插入。因此入队和出队的时间复杂度是O(1),这种方法才是可行的。

3. 实现(C++代码)

//SinglyLink.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 SinglyLinkList{public: SinglyLinkList(); 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();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;}//————————————————————————————————//SinglyLink类实现template
SinglyLinkList
::SinglyLinkList() :m_pHeadNode(new Node
()),m_length(0){}template
bool SinglyLinkList
::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 SinglyLinkList
::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 SinglyLinkList
::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& SinglyLinkList
::GetLength() const{ return m_length;}template
bool SinglyLinkList
::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 SinglyLinkList
::Visit(ElemType* elem, const unsigned int& pos) const{ if (pos >= GetLength() || pos < 0) { return false; } return Search(pos,elem);}template
bool SinglyLinkList
::Empty(){ return !m_length;}template
Node
* SinglyLinkList
::HavaHeadNode(){ return m_pHeadNode;}
//QueueBySinglyLink.h#pragma once#include "SinglyLinkList.h"template
class QueueBySinglyLink{public: QueueBySinglyLink(); bool EnQueue(ElemType elem); bool DeQueue(ElemType* elem); bool Empty(); unsigned int GetLength() const; bool Visit(ElemType* elem, const unsigned int& pos) const;private: SinglyLinkList
* m_pSinglyLink; Node
* m_TopNode;};template
bool QueueBySinglyLink
::Empty(){ return m_pSinglyLink->Empty();}template
unsigned int QueueBySinglyLink
::GetLength() const{ return m_pSinglyLink->GetLength();}template
bool QueueBySinglyLink
::DeQueue(ElemType* elem){ return m_pSinglyLink->Delete(0,elem);}template
bool QueueBySinglyLink
::EnQueue(ElemType elem){ if (m_pSinglyLink->InsertByPosNode(elem,m_TopNode, &m_TopNode)) { return true; } else { assert(false && "Error: QueueBySinglyLink Push failed for allocate node"); return false; }}template
QueueBySinglyLink
::QueueBySinglyLink() : m_pSinglyLink(new SinglyLinkList
()), m_TopNode(m_pSinglyLink->HavaHeadNode()){}template
bool QueueBySinglyLink
::Visit(ElemType* elem, const unsigned int& pos) const{ return m_pSinglyLink->Visit(elem,pos);}
//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; dateStruct.Visit(&tempElem,i); printf("%d ",tempElem); } printf("\n"); printf("\n"); }}
//main.cpp#include "QueueBySinglyLink.h"#include "Util.h"#include 
using namespace std;typedef int ElemType;int main(){ QueueBySinglyLink
testQueueBySinglyLink; Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength()); cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl; for (int i = 1; i != 5; i++) { testQueueBySinglyLink.EnQueue(i); cout << "\nPush:" << i << endl; Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength()); cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl; } for(int i = 1; i!= 5; i++) { int temp; testQueueBySinglyLink.DeQueue(&temp); cout << "\nPop:" << temp << endl; Util::PrintMemory(testQueueBySinglyLink,testQueueBySinglyLink.GetLength()); cout << (testQueueBySinglyLink.Empty() ? "Empty QueueBySinglyLink." : "Not Empty QueueBySinglyLink.") << endl; } return 0;}

4. 程序运行结果

PrintMemory:

Empty QueueBySinglyLink.

Push:1

PrintMemory: 1
Not Empty QueueBySinglyLink.

Push:2

PrintMemory: 1 2
Not Empty QueueBySinglyLink.

Push:3

PrintMemory: 1 2 3
Not Empty QueueBySinglyLink.

Push:4

PrintMemory: 1 2 3 4
Not Empty QueueBySinglyLink.

Pop:1

PrintMemory: 2 3 4
Not Empty QueueBySinglyLink.

Pop:2

PrintMemory: 3 4
Not Empty QueueBySinglyLink.

Pop:3

PrintMemory: 4
Not Empty QueueBySinglyLink.

Pop:4

PrintMemory:
Empty QueueBySinglyLink.

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

你可能感兴趣的文章
Hadoop — HDFS的概念、原理及基本操作
查看>>
机器学习算法原理解析 - 集成
查看>>
Spark SQL基本概念与基本用法
查看>>
Spark RDD基本概念与基本用法
查看>>
Elasticsearch 6.4基本操作 - Java版
查看>>
Hadoop — Yarn原理解析
查看>>
Storm基本原理概念及基本使用
查看>>
Spark源码剖析 - SparkContext的初始化(三)_创建并初始化Spark UI
查看>>
机器学习算法原理解析 - 聚类
查看>>
Spark源码剖析 - SparkContext的初始化(二)_创建执行环境SparkEnv
查看>>
大数据之统计学基础
查看>>
机器学习算法原理解析 - 分类
查看>>
Spark源码剖析 - SparkContext的初始化(一)
查看>>
Elasticsearch-基础介绍及索引原理分析(转载)
查看>>
机器学习算法原理解析 - 回归
查看>>
Spark源码剖析 - 任务提交与执行
查看>>
Spark源码剖析 - SparkContext的初始化(十)_Spark环境更新
查看>>
Spark源码剖析 - 计算引擎
查看>>
Spark源码剖析 - SparkContext的初始化(四)_Hadoop相关配置及Executor环境变量
查看>>
Spark源码剖析 - SparkContext的初始化(八)_初始化管理器BlockManager
查看>>