数据结构之循环队列和栈的应用
前面提到,在队列的顺序存储结构中,必须要讨论顺序队列的数组越界(或上溢)问题。
根据顺序队列的定义,我们可以很轻松的发现,当队列删除一个元素之后,即front指针向后移动之时,往往这个时候就有可能出现所谓的“假溢出”现象,即可能会出现下图所示这般:
解决“假溢出”的办法有很多,其中最为出色的是这四种方法:
一、采用循环队列
二、按最大可能的进队操作次数设计顺序队列的最大元素个数
三、修改出队算法,使得每一次出队列后都把队列中剩余的元素向对头方向移动一个位置
四、修改入队算法,增加判断条件,当假溢出时,把队列中的元素向对头移动,然后完成入队操作
然而,最常用的方法是:循环队列
循环队列是将存储队列的存储区域看成一个首位相连的圆环,即将q->data[0]和q->data[max-1]连接起来,形成一个环形表。
入队操作时:队尾指针加1,描述为q->rear=(q->rear+1)%max;
出队操作时:对头指针加1,描述为q->front=(q->front+1)%max;
然而使用循环队列急需解决的一个问题就是:
当队空的时候:q->front=q->rear;
当队满的时候:q->front=q->rear;
说白了,无法区分到底什么时候队满和队空。
于是解决办法有三种:
一、使用变量(假设为a)计数,入队a+1,出队a-1,队空条件(a==0),队满条件(a>0&&q->rear=q->front)
二、设置一个标志位flag,入队则flag=1;出队则flag=0;若队满则:(q->front=q->rear&&flag==1),若队空则(q->front=q->rear&&flag==0)
三、损失一个空间不用,即front所指处不用,当队列元素为max-1时即认为满了,此时队空(q->front=q->rear),队满(q->front=(q->rear+1)%max
其中第三种办法是最为熟悉的.
当q->rear>=q->front时,循环队列的长度len=q->rear-q->front;
当q->rear<
q->front时,len=q->rear-q->front+max;
汇总:
循环队列的初始化条件:q->rear=q->front=0;
循环队列满条件:(q->rear+1)%max=q->front;
循环队列空条件:q->front=q->rear
循环队列依旧是顺序队列,除了逻辑上不同之外,其余的都是非常的清楚,故循环队列的操作的综合程序与顺序队列的非常相似,若有所需要,可查看博文-顺序队列,在此不再赘述。
栈的应用
用非递归算法将输入的任意一个十进制整数转换为八进制数。
解题思路
这个题目相对简单,放在栈的应用十分合适,将十进制除以8的余数压入栈中,所得商重复上述动作,直至商为0.
代码
#include<stdio.h>
#define max 100
typedef struct
{
int data[max];
int top;
}seqstack;
void initstack(seqstack*s)
{
s->top=0;
}
int gettop(seqstack*s)
{
int x;
if(s->top==0)
{
printf("the stack is empty\n");
x=0;
}
else x=(s->data)[s->top];
return x;
}
int push(seqstack*s,int x)
{
if(s->top==max)
{
printf("the stack is full\n");
return 0;
}
else
{
s->top++;
(s->data)[s->top]=x;
return 1;
}
}
int pop(seqstack*s)
{
int x;
if(s->top==0)
{
printf("the stack is empty\n");
x=0;
}
else {
x=(s->data)[s->top];
s->top--;
}
return x;
}
int main()
{
seqstack stack,*s;
int n=0;
s=&stack;
initstack(s);
printf("input a non number(decade):");
scanf("%d",&n);
push(s,'$');
while(n!=0)
{
push(s,n%8);
n/=8;
}
printf("the octal number:");
while(gettop(s)!='$')
printf("%d",pop(s));
putchar('\n');
return 0;
}
总结
这次满打满算,收获颇丰,除了知晓了队列的奥妙,顺便还体验了一把栈的应用,从中我们可以看出,基本的思想时相对简单的,难的就是如何将思想转换为语言来形容,这是初级开发者的表现,争取再进一步,成为以思想著称的高级开发者!