c语言建立队列
一、顺序队列
因为顺序队列实现比较简单,所以就来谈谈实现的思路和一些注意事项。队列的顺序存储结构
一般在顺序存储结构中,如果用双指针来进行操作,一般移动(或者先移动的都是指向最后边元素的下一个位置,目的是方便操作。队列的顺序存储结构称为顺序队列,是利用一组连续的存储单元(一维数组)依次存放从队首到队尾的各个元素。由于随着人队和出队操作的变化,队列的队头和队尾的位置是变动的,所以应设置两个整型变量front和rear,分别指示队头和队尾在数组空间中的位置,通常称from为队头指针,rear为队尾指针,它们的初值在队列初始化时均应置为0,并约定在非空队列里,队首指针from始终指向队头元素,队尾指针rear始终指向队尾元素的下一个位置。
顺序队列的讨论
"下溢"现象
当队列为空,即
font == rear
,若作出出队列的操作产生的溢出现象,称为下溢。
"真上溢"现象
当
rear == MAXQSIZE
时,若作出入队列的操作产生的溢出现象,称为真上溢。
"假上溢"现象
有真必有假嘛,假上溢指的是随着队列出队与入队的操作,头指针和尾指针只增加不减少,致使被删除元素的空间无法使用。因此,尽管队列中实际元素个数可能远远小于数组的大小,但可能尾指针可能已经超出数组的大小而无法进行入队操作,称为 "假上溢"现象.
二、如何解决"假上溢"问题
- 当出现“假上溢”现象时,把所有的元素向低端移动,使得空位从高端区移向低端区,显然这种方法很浪费时间。
- 将存储队列元素的一维数组首尾相接,形成一个环状。将这种形式表示的队列称为循环队列(Circular Queue)。
- 采用链式队列。
三、循环队列
循环队列说明
在循化队列中进行出队、入队操作时,队头和对尾指针仍要加1。只不过当首、队尾指针指向数组上界( (MAXSIZE−1) )时,其加1操作的结果是指向数组的下界0,循环队列不会上溢。同样是约定在非空循环队列里,队首指针始终指向队头元素,队尾指针始终指向队尾元素的下一个位置。因此,真正实用的顺序队列是循环队列。
循环队列的实现方法
1、设置一个标记以区别队列是空还是满
设置标志flag,当Q.font ==Q.rear 且flag = 0时为队空,当Q.font ==Q.rear 且flag = 1时为队满。
2、使用一个计数器记录队列中元素的总数
设置一个变量count 来记录元素中的个数,当count ==0时为空,当count = =MAXQSIZE -1 时为满
3、保留对空条件,修改队满条件(常用)
少用一个元素的存储单元,未用单元不确定在哪一个位置,约定以“队列头指针在队列尾指针的下一位置(指环状的下一位置)上”作为队列呈“满”状态的标志。当存储循环队列的数组中只有一个空闲单元时,将循环队列视为队满,此时队尾指针和队头指针正好相差1,因此,队满条件为 。(Q⋅rear+1)%MAXQSIZE=Q.font。
循化队列的存储结构定义
# define MAXQSIZE 100 //定义队列最大容量(长度)
#define QElemType int //定义队列元素类型
typedef struct {
QElemType base[MAXQSIZE];
int font, rear;
}SqQueue;
初始化队列
//初始化一个队列
void init(SqQueue& Q) {
Q.font = 0;
Q.rear = 0;
}
设置标志
入队操作
void push(SqQueue& Q, int val){
if(flag == 1){
printf("队列已满\n");
return;
}
Q.base[Q.rear] = val; //添加到队列
Q.rear++;
if(Q.rear == MAXQSIZE)flag =1;
}
出队操作
//出队操作
int pop(SqQueue& Q) {
if (!flag) {
printf("队列为空\n");
return 0;