赞
踩
队列具有以下两个特点
顺序队列的底层使用的是数组,需预先申请一块足够大的内存空间初始化顺序队列。除此之外,为了满足顺序队列中数据从队尾进,队头出且先进先出的要求,还需要定义两个位置指针(top
和 rear
)分别用于指向顺序队列中的队头元素和队尾元素,如图所示:
由于顺序队列初始状态没有存储任何元素,因此 top
指针和 rear
指针重合,且由于顺序队列底层实现靠的是数组,因此 top
和 rear
实际上是两个变量,它的值分别是队头元素和队尾元素所在数组位置的下标。
入队和出队操作的实现思想:
当有数据元素进队列时,对应的实现操作是将元素存储在指针
rear
指向的数组位置,然后rear+1
;当需要队头元素出队时,仅需top+1
操作。
例如,将 {1,2,3,4} 用顺序队列存储的实现操作如图所示:
{1,2,3,4} 入队后,将顺序队列中数据出队的实现过程如图所示:
因此,使用顺序表实现顺序队列C 语言实现代码为:
#include <stdio.h> int enQueue(int *a,int rear,int data) { a[rear]=data; rear++; return rear; } void deQueue(int *a,int front,int rear) { //如果 front==rear,表示队列为空 while (front!=rear) { printf("出队元素:%d\n",a[front]); front++; } } int main() { int a[100]; int front,rear; //设置队头指针和队尾指针,当队列中没有元素时,队头和队尾指向同一块地址 front=rear=0; //入队 rear=enQueue(a, rear, 1); rear=enQueue(a, rear, 2); rear=enQueue(a, rear, 3); rear=enQueue(a, rear, 4); //出队 deQueue(a, front, rear); return 0; }
程序输出结果:
出队元素:1
出队元素:2
出队元素:3
出队元素:4
此方法存在的问题:
将所有数据入队再出队后,指针 top
和 rear
重合位置指向了 a[4]
而不再是 a[0]
。也就是说,整个顺序队列在数据不断地进队出队过程中,在顺序表中的位置不断后移。
顺序队列整体后移造成的影响是:
为了避免以上两点,可以使用下面的方法实现顺序队列。
为了解决以上两个问题,可以使用巧妙的方法将顺序表打造成一个环状表,如图所示:
上图只是一个想象图,在真正的实现时,没必要真创建这样一种结构,我们还是使用之前的顺序表,也还是使用之前的程序,只需要对其进行一点小小的改变:
#include <stdio.h> #define max 5//表示顺序表申请的空间大小 int enQueue(int *a,int front,int rear,int data) { //添加判断语句,如果rear超过max,则直接将其从a[0]重新开始存储,如果rear+1和front重合,则表示数组已满 if ((rear+1)%max==front) { printf("空间已满"); return rear; } a[rear%max]=data; rear++; return rear; } int deQueue(int *a,int front,int rear) { //如果front==rear,表示队列为空 if(front==rear%max) { printf("队列为空"); return front; } printf("%d ",a[front]); //front不再直接 +1,而是+1后同max进行比较,如果=max,则直接跳转到 a[0] front=(front+1)%max; return front; } int main() { int a[max]; int front,rear; //设置队头指针和队尾指针,当队列中没有元素时,队头和队尾指向同一块地址 front=rear=0; //入队 rear=enQueue(a,front,rear, 1); rear=enQueue(a,front,rear, 2); rear=enQueue(a,front,rear, 3); rear=enQueue(a,front,rear, 4); //出队 front=deQueue(a, front, rear); //再入队 rear=enQueue(a,front,rear, 5); //再出队 front=deQueue(a, front, rear); //再入队 rear=enQueue(a,front,rear, 6); //再出队 front=deQueue(a, front, rear); front=deQueue(a, front, rear); front=deQueue(a, front, rear); front=deQueue(a, front, rear); return 0; }
程序运行结果:
1 2 3 4 5 6
使用此方法需要注意的是,顺序队列在判断数组是否已满时,出现下面情况:
顺序队列的存储状态不同,但是判断条件相同。为了对其进行区分,最简单的解决办法是:牺牲掉数组中的一个存储空间。判断数组满员的条件是:尾指针的下一个位置和头指针相遇,就说明数组满了,即程序中第 5 行所示。
链式队列的实现思想同顺序队列类似,只需创建两个指针(命名为 top
和 rear
)分别指向链表中队列的队头元素和队尾元素,如图所示:
上图所示为链式队列的初始状态,此时队列中没有存储任何数据元素,因此 top
和 rear
指针都同时指向头节点。
由此,我们可以编写出创建链式队列的 C 语言实现代码为:
//链表中的节点结构
typedef struct QNode
{
int data;
struct QNode * next;
}QNode;
//创建链式队列的函数
QNode * initQueue()
{
//创建一个头节点
QNode * queue=(QNode*)malloc(sizeof(QNode));
//对头节点进行初始化
queue->next=NULL;
return queue;
}
链队队列中,当有新的数据元素入队,只需进行以下 3 步操作:
elem
;rear
指针指向的节点建立逻辑关系,即执行 rear->next=elem
;rear=elem
;依次将 {1,2,3} 依次入队,各个数据元素入队的过程如图所示:
数据元素入链式队列的 C 语言实现代码为:
QNode* enQueue(QNode * rear,int data)
{
//1、用节点包裹入队元素
QNode * enElem=(QNode*)malloc(sizeof(QNode));
enElem->data=data;
enElem->next=NULL;
//2、新节点与rear节点建立逻辑关系
rear->next=enElem;
//3、rear指向新节点
rear=enElem;
//返回新的rear,为后续新元素入队做准备
return rear;
}
有数据元素需要出队时,按照 “先进先出” 的原则,只需将存储该数据的节点以及它之前入队的元素节点按照原则依次出队即可。这里,我们先学习如何将队头元素出队。
链式队列中队头元素出队,需要做以下 3 步操作:
将元素 1 和 2 出队操作过程如图所示:
链式队列中队头元素出队的 C 语言实现代码为:
void DeQueue(QNode * top,QNode * rear) { if (top->next==NULL) { printf("队列为空"); return ; } // 1、 QNode * p=top->next; printf("%d",p->data); top->next=p->next; if (rear==p) { rear=top; } free(p); }
给出链式队列入队和出队的完整 C 语言代码为:
#include <stdio.h> #include <stdlib.h> typedef struct QNode { int data; struct QNode * next; }QNode; QNode * initQueue() { QNode * queue=(QNode*)malloc(sizeof(QNode)); queue->next=NULL; return queue; } QNode* enQueue(QNode * rear,int data) QNode * enElem=(QNode*)malloc(sizeof(QNode)); enElem->data=data; enElem->next=NULL; //使用尾插法向链队列中添加数据元素 rear->next=enElem; rear=enElem; return rear; } QNode* DeQueue(QNode * top,QNode * rear) { if (top->next==NULL) { printf("\n队列为空"); return rear; } QNode * p=top->next; printf("%d ",p->data); top->next=p->next; if (rear==p) { rear=top; } free(p); return rear; } int main() { QNode * queue,*top,*rear; queue=top=rear=initQueue();//创建头结点 //向链队列中添加结点,使用尾插法添加的同时,队尾指针需要指向链表的最后一个元素 rear=enQueue(rear, 1); rear=enQueue(rear, 2); rear=enQueue(rear, 3); rear=enQueue(rear, 4); //入队完成,所有数据元素开始出队列 rear=DeQueue(top, rear); rear=DeQueue(top, rear); rear=DeQueue(top, rear); rear=DeQueue(top, rear); rear=DeQueue(top, rear); return 0; }
程序运行结果为:
1 2 3 4
队列为空
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。