博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基本数据结构 - 栈和队列
阅读量:6520 次
发布时间:2019-06-24

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

摘要

  本章介绍了几种基本的数据结构,包括栈、队列、链表以及有根树,讨论了使用指针的简单数据结构来表示动态集合。本章的内容对于学过数据结构的人来说,没有什么难处,简单的总结一下。

1、栈和队列

  栈和队列都是动态集合,元素的出入是规定好的。栈规定元素是先进后出(FILO),队列规定元素是先进先出(FIFO)。栈和队列的实现可以采用数组和链表进行实现。在标准模块库STL中有具体的应用,可以参考。

  栈的基本操作包括入栈push和出栈pop,栈有一个栈顶指针top,指向最新如栈的元素,入栈和出栈操作操作都是从栈顶端进行的。

  队列的基本操作包括入队enqueue和出队dequeue,队列有队头head和队尾tail指针。元素总是从队头出,从队尾入。采用数组实现队列时候,为了合理利用空间,可以采用循环实现队列空间的有效利用。

  关于栈和队列的基本操作如下图所示:

采用数组简单实现一下栈和队列,实现队列时候,长度为n的数组最多可以含有n-1个元素,循环利用,这样方便判断队列是空还是满。

栈的C++程序如下所示:

#include
#include
using namespace std;typedef struct stack { int *s; int stacksize; int top; }stack; void init_stack(stack *s,int n) { s->stacksize=n; s->s=(int*)malloc(sizeof(int)*s->stacksize); s->top=0; } bool stack_empty(stack *s) { if(s->top==0) return true; else return false; } bool stack_full(stack *s) { if(s->top==s->stacksize) return true; else return false; } void push(stack *s,int x) { if(stack_full(s)) { cout<<"overflow"<
top=s->top+1; s->s[s->top]=x; } int pop(stack *s) { int x; if(stack_empty(s)) { cout<<"underflow"<
s[s->top]; s->top--; return x; } int top(stack *s) { return s->s[s->top]; } int main() { stack s; init_stack(&s,100); push(&s,19); push(&s,23); push(&s,34); push(&s,76); push(&s,65); cout<<"top is "<
<

队列的C++代码实现:

#include
#include
using namespace std;typedef struct queue { int *q; int head,tail; int queuesize; }queue; void init_queue(queue *q,int n) { q->queuesize=n; q->q=(int*)malloc(sizeof(int)*q->queuesize); q->tail=q->head=0; } bool queue_empty(queue *q) { if(q->head==q->tail) return true; else return false; } bool queue_full(queue *q) { if(q->tail+1==q->head) return true; else return false; } int queue_length(queue *q) { return (q->tail-q->head+q->queuesize)%q->queuesize; } void enqueue(queue *q,int x) { if(queue_full(q)) { cout<<"queue overflow"<
q[q->tail]=x; q->tail=(q->tail+1)%q->queuesize; } int dequeue(queue *q) { int x; if(queue_empty(q)) { cout<<"queue underflow"<
q[q->head]; q->head=(q->head+1)%q->queuesize; return x; } int main() { queue q; init_queue(&q,100); enqueue(&q,10); enqueue(&q,30); cout<<"head: "<
<<" tail: "<
<

问题:

(1)说明如何用两个栈实现一个队列,并分析有关队列操作的运行时间。(始终用一个栈做为出,一个栈作为入队)

解答:栈中的元素是先进后出,而队列中的元素是先进先出。现有栈s1和s2,s1中存放队列中的结果,s2辅助转换s1为队列。

入队时,将元素压入s1。

出队时,判断s2是否为空,如不为空,则直接弹出顶元素;如为空,则将s1的元素逐个“倒入”s2,把最后一个元素弹出并出队。

(如果s1满了,s2既没有装满也不是非空,此时就不能继续入队了;如果s1满了,但s2是空的,则可以先将s1中的元素压人s2中,然后再进队。)

#include
#include
#include
using namespace std;template
class StackToQueue { public: T dequeue(); void enqueue(const T &node); StackToQueue(){} ~StackToQueue(){} private: stack
stack1; stack
stack2; }; template
void StackToQueue
::enqueue(const T &node) { stack1.push(node); } template
T StackToQueue
::dequeue() { if(stack2.empty()&&stack1.empty()) { cout<<"underflow"<
sq; sq.enqueue(1); sq.enqueue(2); sq.enqueue(3); cout<
<

(2)说明如何用两个队列实现一个栈,并分析有关栈操作的运行时间。(始终保证有一个队列是空的)

需要注意的一点是,如果每次入栈都选则将元素插入到第一个队列中,出队时先将前n-1个元素移交到第二个队列中,然后返回队列一中剩余的唯一一个元素,再将队列二中的元素又依次移交回队列一中,这样做未免效率过于低下。

事实上这样的思路我们可以看作是一直选用队列一作为栈元素的存储容器,而使用队列二作为一个出队时的辅助工具,这样每次出栈时来回复制元素容器元素的操作,效率确实低下。因为两个队列完全一样的,所以我们完全有理由让两个队列轮流作为栈元素的存储容器,这样每次出栈时,只需将所有前n-1个元素从一个队列移交到另一个队列中,然后返回最后一个元素作为出栈结果,这样始终至少有一个队列是空的,而每次进栈时,只需将进占元素放在那个非空队列的末尾(如果两个队列均为空,则随便放在那个里面都行)。这样减少了一半的复制操作。

#include
#include
#include
using namespace std;template
class QueueToStack { public: QueueToStack(){} ~QueueToStack(){} T pop(); void push(const T &node); private: queue
queue1; queue
queue2; }; template
T QueueToStack
::pop() { T data; if(queue1.empty()&&queue2.empty()) { cout<<"underflow"<
1) { T temp=queue1.front(); queue1.pop(); queue2.push(temp); } data=queue1.front(); queue1.pop(); } else if(!queue2.empty()) { while(queue2.size()>1) { T temp=queue2.front(); queue2.pop(); queue1.push(temp); } data=queue2.front(); queue2.pop(); } return data; } template
void QueueToStack
::push(const T &node) { if(!queue1.empty())//每次都压入到工作的队列中 queue1.push(node); else queue2.push(node); } int main() { QueueToStack
queue; queue.push(1); queue.push(2); queue.push(3); cout<
<

 上面的top没有写

#include 
#include
#include
#include
using namespace std; /*两个队列模拟一个堆栈*/ /*队列A、B 入栈:将元素依次压入到非空的队列,第一个元素压倒对列A 出栈:把队列A的前n-1个元素倒到队列B,把第n个元素去掉。此时数据在B中,下次操作,则对B操作。 栈顶:把队列A的前n-1个元素倒到队列B,把第n个元素作为栈顶*/ template
class MyStack { public: //入栈,第一个元素进到队列deque1,以后每个元素进到非空的队列 void push(T element) { if (deque1.empty() && deque2.empty()) { deque1.push_back(element); } else if (!deque1.empty() && deque2.empty()) { deque1.push_back(element); } else if (deque1.empty() && !deque2.empty()) { deque2.push_back(element); } } //出栈,将非空队列的前n-1个元素转移到另一个空的队列,删除非空队列的第n个元素 void pop() { if (!deque1.empty()) { int size = deque1.size(); for (int i=0; i
deque1; deque
deque2; }; int main(int argc, char *argv[]) { MyStack
my; for (int i=0; i<10; i++) { my.push(i); } while (!my.empty()) { cout<
<<" "; my.pop(); } cout<

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

你可能感兴趣的文章
北京市交管局联合高德地图发布北京中考出行提示
查看>>
如何防止应用程序泄密?
查看>>
一文带你看懂物联网开源操作系统
查看>>
什么是实践中真正在用的数据科学系统?
查看>>
新型智慧城市:构建“互联网+”新生活
查看>>
韩企全球首造72层3D NAND芯片 下半年或量产
查看>>
《R语言编程艺术》——1.4 R语言中一些重要的数据结构
查看>>
如何让你的手机比别人最先升级到 Android L
查看>>
阿里云开源编程马拉松入围项目
查看>>
Mozilla 开源支持计划:首批捐助 7 开源项目 50 万美元
查看>>
《Photoshop混合模式深度剖析》目录—导读
查看>>
《为iPad而设计:打造畅销App》——抓住iPad的核心用法
查看>>
华尔街宫斗戏升温:银行巨头和纽交所争夺交易数据所有权
查看>>
《精通自动化测试框架设计》—第2章 2.6节使用数据库
查看>>
《网站性能监测与优化》一2.4 软件服务应用网站
查看>>
《HTML5 开发实例大全》——1.26 使用鼠标光标拖动网页中的文字
查看>>
【JSP开发】有关session的一些重要的知识点
查看>>
生产库中遇到mysql的子查询
查看>>
redis debug命令详解
查看>>
3144: [Hnoi2013]切糕
查看>>