队列
- 如果希望循环队列中的元素都能得到利用,则需设置一个标志域tag,并以tag的值为0或1来区分队头指针front和队尾指针rear相同时的队列状态是“空”还是“满”,试编写相应的入队和出队算法
分析:只在队列的结构里设置一个tag,当有元素入队的时候tag为1,当有元素出队的时候tag为0。初始时tag为0。
bool Enqueue(Elemtype x,SqlQueue &Q){
if(Q.rear == Q.front && Q.tag == 1)
return false;
else{
Q.data[Q.rear] = x;
Q.rear = (Q.rear+1)%Maxsize;
Q.tag = 1;
return true;
}
}
bool Dequeue(Elemtype x,SqlQueue &Q){
if(Q.rear==Q.front && Q.tag == 0)
return false;
else{
x = Q.data[Q.front];
Q.front -( Q.front +1)%Maxsize;
Q.tag=0;
return true;
}
}
- Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法
分析:很简单,把队列中的元素入栈,然后从栈中弹出再进入队列即可
void Inverser(Stack S,Queue Q){
while(!QueueEmpty(Q)){
Elemtype x;
Dequeue(Q,x);
Push(S,x);
}
while(!StackEmpty(S)){
Elemtype x;
Pop(S,x);
Enqueue(Q,x);
}
}
- 利用两个栈S1、S2来模拟一个队列,已知栈的4个运算定义如下:
Push(S,x);
Pop(S,x);
StackEmpty(S);
StackOverflow(S);
如何利用栈的运算来实现该队列的三个运算
Enqueue;
Dequeue;
QueueEmpty;
分析:将两个栈底对底链接起来
如果是出队操作,使用S1入栈,然后将S1中的元素弹出送入S2,从S2中再弹出元素;
(出队操作使用S2出栈表示,当S2当前为null的时候将S1中的元素全部送入S2中,然后再进行出栈操作)
如果是入栈操作,使用S2出栈,然后将S2中的元素弹出送入S1,从S1中再送入元素
(入队操作使用S1入栈表示,如果S1满,必须先保证S2为空,将S1当前的全部元素送入S2然后再入栈S1)
bool Enqueue(Stack &S1,Stack &S2,Elemtype e){
if (StackOverflow(S1)&&StackEmpty(S2)){
//如果S1已经满了,但是S2是空的
while(!StackEmpty(S1)){
Elemtype x;
Pop(S1,x);
Push(S2,x);
}
Push(S1,e);
return true;
}
if(!StackOverflow(S1)){
Push(S1,e);
return true;
}
return false;
}
bool Dequeue(Stack &S1,Stack &S2,Elemtype e)
{
if(StackEmpty(S2)&&!StackEmpty(S1))
{
while(!StackEmpty(S1)){
Elemtype x;
Pop(S1,x);
Push(S2,x);
}
Pop(S2,e);
return true;
}
//if(StackEmpty(S1)&&StackEmpty(S2))
//return false;
//如果要是真的有这个判断的话是具体使用的时候错误的提示信息不同,这里都是返回false就作区分了
if(!StackEmpty(S2))
{
Pop(S2,e);
return true;
}
return false;
}
bool QueueEmpty(Stack S1,Stack S2){
if(StackEmpty(S1)&&StackEmpty(S2))
return true;
else
return false;
}
栈和队列的应用
- 铁道车厢调度(两侧铁道均为单向行驶道,火车调度站有一个用于调度的“栈道”)火车调度站的入口处有n节硬座和软座车厢(分别以H和S表示)等待调度,试编写算法,输出对这n节车厢进行调度的操作(即入栈或出栈操作)序列,以使所有的软座车厢都被调整到硬座车厢中之前。
分析:很明显调度的栈道就是FIFO的栈,利用栈的实现序列重排。当前的所有硬座车厢都进入栈(有一个判断当前车是硬座还是软座)
void Train_Arrange(char *train){
char *p=train,*q=train,c;
stack s;
InitStack(S);
while(*p){
if(*p=='H')
Push(s,*p);
else
*(q++)=*p;
p++;
}
while(!StackEmpty(s)){
Pop(s,c);
*(q++)=c;
}
}
- 利用一个栈实现以下递归函数的非递归计算:
Pn= 1 n=0
= 2x n=1
= 2xPn-1(x)-2(n-1)Pn-2(x) n>1
- 某汽车轮渡口,过江渡船每次能载10辆车过江。过江车辆分为客车类和货车类,上渡船有如下规定:同类车先到先上渡船;客车先于货车上渡船,且每上4辆客车,才允许放上一辆货车;若等待客车不足4辆,则以货车代替;若无货车等待,允许客车都上船。试设计一个算法模拟渡口管理。
分析:
🐖凡是涉及到等待资源这种的使用队列来实现,客车一个队列,货车一个队列,过江渡船一个队列。然后就直接按照题目中的四种情况用代码写出来就行。等待客车的辆数计算通过一个计数变量,每次符合了就清零。
Queue q1,q2,q3;//q1_bus,q2_lobby,q3_manager
void manager(){
int i=0,j=0; //number_bus,number_manager
while(j<10){
if(!QueueEmpty(q1)&&i<4){
Elemtype x;
Dequeue(q1,x);
Enqueue(q3,x);
i++;
j++;
}
else if(i==4&&!QueueEmpty(q2))
{
Elemtype x;
Dequeue(q2,x);
Enqueue(q3,x);
i=0;
j++;
}
else{
while(j<10&&i<4&&!QueueEmpty(q2))
{
Elemtype x;
Dequeue(q2,x);
Enqueue(q3,x);
i++;//i>4,break
j++;
}
}
if(QueueEmpty(q1)&&QueueEmpty(q2))
j=11;//break the "while (j<0)"
}
}
- 设计一个栈,使它可以在O(1)的时间复杂度内实现push、pop和min操作,所谓min操作是得到栈中最小元素
思路:使用双栈,空间换时间,使用一个普通栈实现push和pop,使用另一个栈用栈顶存储当前的最小值,直接弹出辅助栈的栈顶即可。