栈与队列 循环队列

1.操作受限的线性表(栈和队列,即双端队列:只能在表头或表尾处做插入和删除的线性表(对于栈和队列来说,插入即输入,删除即输出)

特点:后进先出(LIFO:last imput first output)

  

a开头的:ab,bc,ad    b开头的:ba,bc,bd   c开头的:ca,cb,cd  d开头的:dc,da(X),db(X) 

abcd abdc acbd acdb adcb     5种

bacd badc bcad bcda bdca     5种

cbad cbda cdba                      3种

dcba                                        1种

已知入栈顺序是1,2,3....n

如果第一个出栈的是i,则表明前面的i-1个元素已经在栈中了。之后出栈的必然是i-1,i-2...1

是降序排列的

 例题:入栈序列是递增升序入栈1,2,3,4,5,确实是递增的                                                     A项:第一位是5,后面小于5的数应该是是降序排列的                                 

   B项:第一位是4,小于4的数是1,3,2,但1,3,2不是降序排列的                                                C项:第一位是4,小于4的数是3,1,2,但3,1,2不是降序排列的                                                  D项:第一位是3,小于3的数是2,1是降序排列的。再看2,再看1,再看5,再看4。每一位都要满足后面小于它的数是降序排列的

入栈序列是降序

每一位都要满足后面大于它的数是升序排列的

A:第一位是2,大于2的数是3,4,5,6,是升序排列的 ;对。每一位都符合

B:第一位是3,大于3的数是4,6,5,不是升序排列的 ;错

                                                                            入栈序列≠输入序列          因为p1=n, 该题的输出序列只能降序排列

n      n-1       n-2   ...  3  2 1                            代入i是2的话pi=p2=n-1来判断,故选C 

           输出第一个元素是i,出栈的序列就有i种,所以第j个输出元素是不确定的

p2是n,后面出栈的肯定是小于n 的且为降序的,只看p1的取值即可,有n-1种出栈序列。例如p1为5,先把1.2.3.4.5入栈,之后5出栈(p1),再将6.7.8.9...n入栈,n出栈(p2)



 因为入队列和出队列的顺序一样,所以7个元素出栈的顺序已知。


     队列                   

    删除端:出队列(队头)

在队头处做出队列的操作     在队尾处做入队列的操作              特点:先进先出   

 直接根据尾指针rear找到尾结点,做插入时,不需要遍历整个链队列

​​​​​​  

1.可以颠倒次序,求逆序:一个字符串,每次读的时候,是以a,b,c,d的顺序读的,输出是d,c,b,a的顺序                   2.函数机制的实现:当调用函数时,是在栈区里面的  

要求栈和队列的插入和删除的时间复杂度都是O(1)

存储栈:顺序存储(顺序栈||循环队列)&&链式存储(链栈||链队列

已知顺序表在表尾处做插入和删除都是O(1),base可直接代表数组(顺序表)的起始地址,而top可以是下标,也可以是地址***,可以指向栈顶元素,也可以定义成指向将要入栈的位置***

top做下标时:s.base[top]

top做地址时:*top

top可以是栈顶元素的下标和地址,也可以指向将要入栈的位置

 

 *S.top++=e:首先++和*的优先级一样 又因为是(单目运算符)右结合的(先执行右边的运算符),先做红圈里的, *(s.top++)就是把原来top的值(还没递增时)取内容,放在e中,e放在了S.top原来未加1的值中

如  i=1;    j=i++;          则i=2,j=1

如   i=1;   j=++i; 则i=2;j=2;i++与++i中,i都会做自增操作,只是表达式的值不一样,一个是i自增前的,另一个是自增后的



 

 链表每次在表头出做插入和删除O(1)       

 入栈插在首元结点的前面,出栈即删除首元接点

 栈的应用 之表达式求值

例如3*(7-2)#,使用两个栈来存,一个专门盛操作数(OPND栈),一个专门盛运算符(OPTR栈)

在读入数据之前,先定义一个’#‘放在OPTR栈中,认为#的优先级小于all运算符优先级的,因此,在读入第一个’*‘时,就可以和#进行优先关系的比较了

当读到的表达式是运算数时,直接让运算数算数栈

当读到的表达式是运算符ch时,OPTR的栈顶元素和ch要进行优先关系的比较:                   1.当栈顶元素的优先级<ch时,让ch入栈                                                                                    2.当栈顶元素的优先级>ch时,先做栈顶元素的运算:如减号的优先级>右括号,即先做读减号的运算,减号出栈,同时2  、7出OPND栈,做7-2的运算,运算结果入OPND 栈

 

 此时OPTR的栈顶元素是左括号,重新让读到的运算符右括号与栈顶元素进行比较。左右括号的优先级是相等的,所以让左括号出栈 即可。再读下一个,读到了#,而OPTR中新的栈顶元素是*,*的优先级>#的优先级。故先做*运算,让*出栈,5、3也出OPND栈 ,#入栈

 

 

将"中缀表达式转为后缀表达式"的过程==表达式求值

即求:运算符栈的情况 

当读到*,*与#比较,(优先级关系的比较)>,*入栈P。当读到+,'+'<'*','*'出栈O,+>#,+入栈P。当读到/,/>+,/入栈P。当读到#,#</,/出栈O。此时#<+,+出栈O

C

 

首先+入栈,*>+,*入栈,再读+,+<*,*出栈。此时左边+>右边+,左边+出栈。再读左括号>+,左括号入栈,再读*,*>左括号,*入栈,再读+,+<*,*出栈,+>左括号,+入栈,读到了f,截止 B

 前缀或后缀表达式不带有括号。后缀表达式求值是最简单的,操作数已经存好了,运算符直接出栈即可

 此时,第一个操作数是a,第二个操作数是bc+所得结果

 此时,第一个操作数是abc+*所得结果,第二个操作数是d

 若是求前缀表达式:

+bc->*a+bc(此时,第一个操作数是a,第二个操作数是+bc所得结果)->-*a+bcd

 

 

后缀表达式只设一个运算数栈即可,当根据化得的后缀表达式,读到运算数时入栈,读到运算符时,相应的操作数出栈 

a,b,c入栈,读到*,b,c出栈,结果b*c入栈,读到+,a也出栈,a+b*c结果入栈

循环队列

 判断题:所谓“循环队列”是指用单向循环链表或者循环数组表示的队列。 ×              

循环队列指的是后者,用数组表示的队列,利用求余数运算使得头尾相接。 循环队列本身是一种顺序存储结构,而循环列表是一种链式存储结构。两者之间是平级关系。 

1.队头元素并不是从下标为0的位置开始存放的(因为如果出队删除的话,还需前移覆盖浪费大量空间),设置front记录队头元素的下标

用取余将数组看做循环数组,循环队列是队列采用了顺序存储结构,用数组来存的

2.头尾指针下移

3.头尾指针类型为整形,是下标。base是数组的起始地址

其出入队列时间复杂度均为O(1)

 就是根据这个来算的

也是循环队列元素的个数

根据题意画个图看看即可

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值