数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

2024-06-29 1644阅读

1.栈

1.1栈的概念

    栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除数据操作。进行数据插入和删除的一端叫做栈顶,另一端叫做栈底。栈的元素遵守后进先出(Last in First out)的原则。

   压栈:数据的插入,也叫做进栈和入栈。

   出栈:数据的删除。

你可以把栈想象成羽毛球桶最后装进去的那个羽毛球,不出意外的话,绝对是第一个被拿出来的

1.2栈的实现

 1.2.1数组实现栈

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

在栈顶的一端进行数据的插入和删除

1.2.2单链表实现栈

   数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

单链表让尾插那边做栈顶的话,出数据不好出,找不到前一个数据 ,每次都要去遍历链表 ,很麻烦,所以想用单链表实现栈的话最好用头插的方法。

1.2.3双向链表实现栈

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

双向链表虽然比单链表灵活但是会多开一个空间,所以能用单链表解决的就用单链接表,但有些时候如果很麻烦的话,我们也会不计较这一点空间的浪费。

1.2.4他们之间的对比

 数组实现栈缺点:需要扩容,会造成时间、空间上的浪费。优点:CPU高速缓存很好。

单链表实现数组优点:不需要扩容,做到有多少数据就开多少的空间。缺点:CPU高速缓存不是很好,双向链表,至于能用单向链表的就用单向链表,可以减少空间上的浪费。

所以综上所述,我们可以选择数组或者单量表实现栈,在这里我用数组来实现。

1.2.5栈的实现

首先我们定义一个栈

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

实现栈的一些接口:

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

初始化:

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

这里需要注意一下:你可以先给数组a开空间 pst->a=(STDataType*)malloc(sizeof(STDataType));

但也可以像我一样选择不开;开有开的玩法,不开有不开的玩法。

还有一个就是top的问题,如果你想让top指向的是栈的位置,那么你可以初始化top的值为-1;

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

这种情况这里的数据为top+1;

当你想让top就是栈里一共有多少元素时 那么top初始化为0;

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

top的赋值跟我常规化的思维有一定的偏差。这里我初始化top=0;

栈的插入:

插入之前我们需要进行空间的大小的判断,如果空间不够那么就要得增大空间,要不然怎

么能在塞数据呢?

扩完容之后我们就在栈顶(数的尾部)进行插入数据就可以了

不会扩容的可以看一下我前面写的动态内存管理,

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

这是我的代码,大家可以参考一下!不过你写的时候不可以偷看我的代码,要自己写才会进步!

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

接下来是Pop,对栈的数据删除!你一定要记得栈只能在一端修改数据(栈顶),不要忘记了栈的规则:后进先出

删除就很简单了,只需要将Top--就可以了,你想,当top==0时候是一个数据都没有,当插入一个数据时top==1,也就是Top往前走了一步,而数组里的数据对应的下标是从0开始的,所以,以我这种情况Top==0,往里面插入数据,,想要访问数组里的元素时是不是要要让top-1才能访问到,并且这里top-1就是栈顶的元素了。

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

差不多就像这样,当你访问数据时反问的是top-1的位置,所以删除数据只需要将top--就行

删除前要记得检测top的值top不能小于1,要不然会越界

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

取栈顶的数据:

这个就很好写了,只需要返回栈顶的数据就可以了,而栈顶的数据对应的下标为top-1,当然我这是初始化top为0的时候,当top为-1时,top对应的下标就是栈顶的数据,这个的根据实际情况,

在取数据时也要记得检测数组是不是为空

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

栈的判空:

实际就是检测数组(链表)不为空,为空就放回真,不为空就返回假:

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

忽视我的注释,注重理解哈。

栈里的元素个数就是top的值,所以直接返回top的值就行;

capacity就是空间大小直返回就行

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

像这样,我们就把栈实现出来了,你也快去试试吧!

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

2.队列

2.1队列的概念

只允许在一端进行插入数据操作,在另一端进行数据删除操作的特殊性线表队列是先进先FIFO(first in first out)入队列:进行插入数据的一端称为队尾;出队列:进行删除的一端称为对头

2.2队列的用途

队列有绝对的公平性,当你想让某些数据先进先出时,你要想到队列。

比如:QQ的好友推荐,QQ会给你推荐一些陌生的好友,那这些好友是怎么来的呢?

其实这些陌生人是根据你的QQ好友进行推荐给你的,就相当是你好友的好友,如果你有多个好友都有这个陌生人的QQ,那么这位陌生人的QQ推荐度是很高的。

这个就是广度优先问题;

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

你可以把小明和小明的好友和他的好友的好友全部存在一个队列里,让小明先放其次是他的好友,以此类推,当然这个依然存在一些问题,比如当出小艾的时候你不知是小张还是小李的好友是,所以我们还有对这个算法进行优化,在后面我们会用到树来优化这类问题。所以留个关注,以免找不到我。

2.3队列的实现

好了,看完上面的你是不是也觉得队列很牛,那么接下来我们就一步一步地去实现它

2.3.1队列的构建

队列可以用数组或链表来实现,主要是做到能存储数据并且在一端入数据在另一端出数据的作用就行了,比如你用数组,可以定义两个变量head和tail来指向队头和队尾,入数据时再tail的位置然后++tail出数据时访问的就是head的位置,访问完之后让head++比如你可以这样出数据

for(int i =head;ihead==NULL)那么就是说明没有一个节点(数据),我们就要去申请一个节点并且让head和tail都指向这个节点

如果有节点的话,直接在tail的后面接上就可以了

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

对照的上面的图理解;

每次插入数据都要去开开辟一个新的节点,你也可以单独写一个函数出来,创建新节点的时候去调用就可以了。

删除

删除和销毁的原理差不多,先存下一个的地址:在把这地址删除就可以了

要注意的是,当只有一个节点的时候,需要把head和tail指针都置为空

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

判空:

当个数size为0的时候就是空的所以我们只要返回判断size的值是不是为空的,

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

返回队头数据:

只需要返回head节点对应的值

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

返回队尾数据:

返回tail节点对应的值

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

到这里我们的队列就已经实现出来了。

3.经典题目:

3.1循环队列

循环队列故名思意就是空间可以循环利用;空间大小固定。

就比如排队体侧,如果规定只能进入多少人,如果这个满了,那么就不能再进入了,只有当一些人测完出去了,才能在进人。

那么我们怎样去实现它呢?是用数组呢?还是用链表呢?

当然两个都是可以的哈,只要你能实现的出来:

先来看链表:

单链表实现循环队列:

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

思路和我们上面创建链表的差不多,但是要多开一个空间,避免假溢出的问题,因为head和tial开始就指向第一个节点,这种情况就是左闭右开,如果你不想额外开空间,那么就要考虑左闭右闭,链表判满很简单,tial的下一个是head就是满,head==tail就为空,或者是在定义一个size去计算队列里的数据,进行判空和判满。难点在于取队尾的数据,队尾的数据=tial-1,但是单链表不好搞,除非你用双向循环链表或者是遍历单链表(这个比较好时,你会选择?)还有一种方法就是在定义一个指针指向tail的前一个节点。这些办法都可以解决。不过各有各自的难度。那我们来看一下数组。

数组:

如果是数组的话,我们需要定义三个变量head,tail和k,k是确定队列的空间大小,

假设k=4;

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

初始化的时候还是一样的head和tail都是0,插入数据插入到tail的位置然后tail++;删除的时候head++;当tail位置如上图形式,在插入数据时,tail要++,怎么回绕到开头的位置呢?其实很简单只需要%一下,先++在%k就回到了开头的位置了,

那什么时候为空什么时候为满呢?

1.为空时head==tail

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

2.为满时head还是==tail,

这时是不是矛盾了,所以这种方案行不通!

如何解决这个问题呢?

第一种,在增加一个size变量当size=k的时候为满,

第二种,额外开空间

head==tial为空,tail的下一个是head就为满,(tial+1)%(k+1)=head

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

数据结构——栈和队列,循环队列,两队列实现栈,两栈实现队列,括号匹配问题

(tial+1)%(k+1)=head都满足所有判满的情形,也很好的区分开了判空和满的问题,

空和满的问题解决了,那么就是去队头和队尾的数据了

队头很好取,队头就是head,队尾是一个难点

队尾的数据是tail-1的位置

分析:

1.当tial在2~最后一个空间之间任意一个空间时队尾的数据就是tial-1,

2.如果tial在第一个的位置时,此时tial=0,tial-1=-1,队尾的数据是最后一空间,最后一个空间的下标为4,所以我们的问题是怎样让tial=4,是不是让tial直接+k(4)就可以了,此时我们可以这样去判断

if(tial>0&&tial

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]