栈和队列的介绍

1.栈

1.什么是栈

栈其实是一种特殊的线性表,但是它与线性表不同的是,栈只允许在固定的一端插入和删除元素,这一端称为栈顶,与之相反的一端称为栈底。因此栈中的元素就遵循一种后进先出的原则。

入栈:即向栈顶插入元素

出栈即在栈顶进行删除操作

这是一个简单的入栈、出栈的模拟示意图,也就是说,栈必须从栈顶进入,也必须从栈顶删除,不能从栈底进行任何的操作。

2.栈的实现

栈的实现可以用数组或者链表来实现,本文介绍以数组来介绍,两个方式在实现上方法类似。

首先我们还是分为Stack.h和Stack.c一个头文件和源文件来实现:

首先我们定义好栈的核心结构,SDataType*_a是来存储栈里面内容的一个数组,int top是指向栈顶元素的下一个位置,int capacity 是栈里有多少个元素。接下来我们就来实现相关的接口:

2.1栈的初始化:

这里初始化比较简单,就不做详细说明。

2.2入栈:

这里入栈和顺序表类似,如果栈的元素个数和空间大小一样,那么我们就需要扩容(每次变成原来空间大小的二倍),但是我们初始化的时候给的大小是0,因此我们使用了一个三木操作符,创建了一个newcapacity来保证我们的空间大小是足够的。当我们realloc成功了之后,我们把新的数组tmp给原来的_a,并且新的newcapacity给我们的capacity来保证下次判断正确,然后进行插入x操作,并且把top加1,这就是我们入栈的操作。

2.3出栈:

出栈也比较好理解,我们只需要将pst中的top大小减1即可,因为是数组,所以就实现了出栈操作,但是要注意,我们在对top减1的时候,要注意top需要大于0。

2.4获取栈顶的元素:

我们在之前已经提到过,我们这里的top指的是栈顶的下一个位置,因此我们在return 的时候应该是返回top-1位置的元素,这个位置也就是栈顶的元素,同时也要注意top大于0,因为top==0的时候没有数据可以返回。

2.5获取栈的有效数据个数:

因为我们使用的是数组,而top刚好指向的就是栈顶数据的下一个位置的下标,也刚好就是数组有效长度的大小,因此我们返回top即可。

2.6判断栈是否为空:

首先这个函数返回类型是bool类型,因此我们在使用的时候需要包含 <stdbool.h>这个头文件。这个函数比较简单,其实里面就是一句代码 return pst->top == 0; 如果pst->top == 0那就说明栈是空的,返回true,如果pst->top != 0那就说明栈不是空的,返回false。

2.7销毁栈:

销毁栈也比较简单,我们先把pst里面的数组_a释放了,因为这个数组是我们realloc出来的,然后我们将_a置空,最后把top和capacity赋值为0即可。

2.队列

1.什么是队列

和栈相比较,那么什么是队列呢?那么我们来看,队列和栈刚好是一个类似的结构,但又不同。

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的的书线性表,队列具有先入先出的性质。入队列:进行插入操作的一段称为队尾出队列:进行删除操作的一端称为队头

这就是一个队列的大致示意图,我们必须满足第一个进入队列的数据第一个出队列。

2.队列的实现

实现队列同栈类似,都可以使用链表或者数组,但是队列使用链表更优,因为出队列需要在数组的起始位置来操作,效率没有链表高。

还是一样,我们先在.h头文件中定义好队列的相关内容。QNode就是链表的一个节点结构体,而Qpoint是因为我们之后向减少传参,因此我们将头节点、尾节点和队列的长度size定义在一个结构体里面。

2.1队列的初始化:

初始化把phead、ptail置为空,并且给size赋值为0,我们队列的初始化就完成了。

2.2入队列:

入队列较栈的插入复杂一点,但其实也是很简单的。首先每次入队列的时候我们肯定要malloc一个队列的节点,然后把节点的相关内容赋值好,接下来就是判断phead和ptail是否为NULL也就是判断是否是第一次插入,如果是第一次插入那就p->phead = p->ptail = newnode;否则就进行p->ptail->next = newnode;和p->ptail = newnode;操作。这就是入队列的一个基本操作,最后别忘了          p->size++,因为我们每次入一个数据,队列中就多了一个,所以size要加1。

2.3出队列:

在进行出队列操作之前,我们要先判断一下队列中size是否为0,因为队列中如果没有元素,那么我们就不能进行出队列的操作。我们先思考一下这种情况:如果队列里面只有一个元素,也就是p->phead == p->ptail此时要进行出队列,我们只需要free掉这个节点,然后把phead和ptail置空即可。其他情况我们提前用next存储phead的下一个节点,然后free掉phead,并且把next赋值给phead即可,最后不要忘了我们已经有一个数据出队列了,所以我们的size要减1。

2.4队列的头元素:

这个比较简单,首先判断phead是否存在,也就是队列不能为空,然后我们只需要return 返回phead的值val即可。

2.5队列的尾元素:

和找头元素一样,首先判断ptail是否存在,然后返回ptail的值val即可。

2.6获取队列中数据的个数:

因为我们提前定义好了size就是队列中数据的个数,因此我们直接返回size的大小即可。

2.7判断队列是否为空:

如果队列里面的size为0了,那么队列就为空了,return p->size == 0;为真就返回true,也就是为空,否则返回false队列不为空。

2.8销毁队列:

销毁队列也比较简单,和之前学过的链表的销毁一样,我们只需要一个节点慢慢free即可,最后把phead、ptail置空,并且给size赋值为0,就完成了队列的销毁。

总体来说栈和队列的实现比较简单,因为之前的顺序表和链表的基础,如果基础比较好,那么栈和队列肯定很顺利就能理解。以上内容如有错误,欢迎批评指正!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值