1.栈和队列的差别:
D和s都一样,p不一样;
1、队列先进先出,栈先进后出。
2、对插入和删除操作的"限定"不同。
栈是限定只能在表的一端进行插入和删除操作的线性表。
队列是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。
3、遍历数据速度不同。
栈只能从头部取数据,也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数
据开辟临时空间,保持数据在遍历前的一致性。
队列则不同,它基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时
空间,因为在遍历的过程中不影像数据结构,速度要快的多
2.队列和栈两种数据类型的结构和差异
栈和队列的异同:
栈和队列都是线性表,都是限制了插入删除点的线性表(或者说是控制了访问点的线性表)
共同点:
都是只能在线性表的端点插入和删除
不同点:
栈 插入和删除都在线性表的同一个端点,该点通称栈顶,相应地,不能插入删除的另一个端点通称栈底,
其特性是后进先出。
队列 在线性表的表头插入,表尾删除,表头一般称队头,表尾一般称队尾,其特性是先进先出
相同之处:n个(同类)数据元素的有限序列称为线性表。线性表的特点是数据元素之间存在“一对一”的关
系,栈和队列都是操作受限制的线性表,他们和线性表一样,数据元素之间都存在“一对一”的关系不同之
处:栈只允许在一段进行插入或删除操作的线性表,其最大的特点是“先进后出或后进的先出”;
对列是只允许在一端进行插入,另一端进行删除操作的线性表,其最大的特点是“先进先出
3.基础知识题
(1)Status algo1(Stack S){
int I,n,A[255];
n=0;
while(! StackEmpty(S)) {n++,Pop(S,A[n])};
for(i=0;i<=n,i++) Push(S,A[i]);}
//分析上述代码的功能:
//当栈非空的时候,栈出栈,元素放进A李,然后把元素再放进去。实现的是栈的逆置。
//可以用数组实现,因为数组可以随机存取
(2)Status algo2(Stack S,int e)
{
Stack T; int d;
InitStack(T);
while(! StackEmpty(S))//栈不空
{
Pop(S,d);//出栈到d
if(d !=e) Push(T,d); //如果d不等于e,就把元素入栈到T里边去
}
while(! StackEmpty(T)) //T不空
{
Pop(T,d);// T的元素又给push到S里边去了
Push(S,d);
}
}
//辅助变量T,初始化d;
//算法的功能是把S中与e相等的元素删除掉
4.简述一下算法的功能
void algo3(Queue & Q) //Q是一个队列
{
Stack S:int d; //S是一个栈作为辅助空间,d作为辅助变量
InitStack (S);
while(!QueueEmpty(Q))
{
DeQueue(Q,d);Push(S,d); //出队列,再把d放进去S中
}
while(! StackEmpty(S))
{
Pop(S,d);EnQueue(Q,d);
}
}
//假设front 1 2 3 4 rear 4321 S
//实现的是队列的逆置
3.6试证明,若借助栈由输入1,2,...n得到输出序列为p1,p2,...pn,他是由输入序列的一个排列,则在输入序列中不可能出现这样一个情形,存在这i<j<k,使得pj<pk<pi;
证明:分析:先以三个元素为例,然后再扩展到n个元素
输入序列:1 2 3
输出: p1 p2 p3
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2 此为非输出队列:正是这里说的不存在的情形。
1<2<3 (p1,p2,p3) = (3,1,2) p2<p3<p1
证明:反证法:假设存在这种情况:存在着i<j<k,使得pj<pk<pi
因为i<j<k,所以出栈序列应该是pi,pj,pk ----------(1)
由栈的运算规则:LIFO,
要使pi比pj和pk先出栈,而pi最大,这样pj和pk就要比pi先入栈
由假设知:pj<pk,那么入栈时顺序应该是pj、pk。那么出栈时应该pk,pj----------(2)
以上得出矛盾(1)(2)
所以不存在这种情况
5.试写一算法,识别依次读入的一个以@为结束符的是否形如‘序列1&序列2’模式的字符序列,其中序列1和序列2都不含字符&,且字符2是字符1的逆序,如‘a+b & b+a’
分析:算法中采用哪种数据结构。
a 初始化一个栈S
b 依次读入字符,并压栈
c 当字符为&时,依次读入下面的字符,并与栈元素比较,有一个不相等,则ERROR
d 字符结束后,栈空,则OK,否则ERROR
算法:
int symmetry()
{ //使用栈,对读入的字符在&之前都压栈,之后弹栈并与读入数比较,知道栈空并且读入数为@是对称,否则是不对称
InitStack(s);//初始化一个栈
scanf(ch);//读入一个字符
while(ch<> “&” )//当字符不是&的时候
{ push(s,ch);scanf(ch);} //就把字符入栈,把&前边的字符读入即序列1
scanf(ch);Gettop(s,x);//遇到&,之后停止循环,再读入一个字符,即序列2的第一个字符,取s的栈顶元素,仅仅是取栈顶元素
while(ch <> “@” && empty(s)) //读到字符不是结束符并且栈不空
{pop(s,x);if(ch == x){ scanf(ch);Gettop(s,x);} //栈顶元素pop,如果相等,继续匹配,再读下一个字符
else return 0;
}
}
}//syummety
//Gettop是不是可以省略;也可以。
6.假设带有头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(不设头指针),编写相应的队列初始化,入队和出队的算法。
分析:入队:在循环链表的最后一个结点插入一个结点
出队:在表头删除元素
出队算法:
Status DeQu(LinkQueue &Q,ElemType &e)
{
if Q.rear->next=Q.rear return Exit(Empty);//队列空
P->next =R->next;
e = R->data;
if R=Q.rear Q.rear = P;
free(R)
}
![](https://i-blog.csdnimg.cn/blog_migrate/248d3c842a4f12a556309c3bf0fa6c97.jpeg)