队列<C语言版>

队列的定义

  队列是一种常用,重要的数据结构。它是一种只允许在一端进行插入操作(入队),在另一端进行删除操作(出队)的运算受到限制线性表,简称“队”。与同线性表相同,逻辑结构仍是一对一的关系。队列采取一种先进先出的数据结构(FIFO结构)。队列存在两种存储结构:顺序存储结构和链式存储结构。

  队列如同排队打饭,先排的人先打饭,然后出队,后来的人排后面,后打饭。 

顺序队列

队列的顺序表示

  顺序队列是用一组地址连续的存储单元,依次存放从队头到队尾的数据元素。队列表示中需要两个指针——头指针front和尾指针rear,分别指向队头元素和队尾元素。定义如下:

typedef struct {
	int* base;
	int front;
	int rear;
}SqQueue;

假溢出

  尾指针rear移动到我们可以进行队列操作的范围之外去了,我们称呼作为队列用的存储区还没有满,但队列却发生了溢出,我们把这种现象称为"假溢出"。

 首先我们有一个顺序队列(上图),这个队列的大小为5,其已经包含了四个元素data1,data2,data3,data4,接着,我们对这个队列进行出队操作,出队2个元素,队列就变成(下图)

  那么我们接着再进行入队操作,我们入队2个元素,分别是data5和data6,此时我们已经发现问题了,尾指针移动到我们可以进行队列操作的范围之外去了,而1,2位置却没有存储,这就是假溢出。

 循环队列

  为了解决“假溢出”现象,我们的方法就是将顺序队列的数组看成一个头尾相接的循环结构。称为循环队列。

但这就有一个问题:当rear==front时,该是判满还是判空呢? 

解决方案:

方案1.另外设计一个标志区别队空队满。

方案2.设一个变量,统计元素个数。

方案3:少用一个元素空间。当队尾指针指的空闲单元的后继单元是队头元素所在单元时,队满。

我们这里采取方案3,则有:

队满:(Q.rear+1)%MAXSIZE==Q.front;

队空:Q.rear==Q.front;

循环队列的操作

初始化

  采用动态分配

void InitQueue(SqQueue& Q) {
	Q.base = (int*)malloc(MAXSIZE*sizeof(int));
	Q.front = 0;
	Q.rear = 0;
	return;
}
求队列长度

  

int QueueLength(SqQueue Q) {
	return((Q.rear - Q.front + MAXSIZE) % MAXSIZE);
}
 入队
void EnterQueue(SqQueue& Q, int e) {
	if ((Q.rear + 1) % MAXSIZE == Q.front) {
		printf("ERROR");
	}
	else
	{
		Q.base[Q.rear] = e;
		Q.rear = (Q.rear + 1) % MAXSIZE;
	}
	return;
}
出队
void DeleteQueue(SqQueue& Q, int& e) {
	if (Q.front == Q.rear) {
		printf("ERROR");
	}
	else
	{
		e = Q.base[Q.front];
	}
	Q.front = (Q.front + 1) % MAXSIZE;
	return;
}

链队

  若用户无法估计所用队列长度,采用链队列,不需要担心溢出情况。定义如下:

typedef struct Qnode{
	int data;
	struct Qnode* next;
}Qnode,*QueuePtr;

  同时一个链队列需要头指针和尾指针,故还需定义如下:

typedef struct {
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;

初始化

void InitQueueLink(LinkQueue& Q) {
	Q.front = (QueuePtr)malloc(sizeof(Qnode));
	Q.rear = (QueuePtr)malloc(sizeof(Qnode));
	Q.front->next = NULL;
	return;
}

销毁链队

void DestoryQueue(LinkQueue& Q) {
	while (Q.front)
	{
	Q.rear = Q.front->next;
		free(Q.rear);
		Q.front = Q.rear;
	}
	return;
}

入队

void EnterQueueLink(LinkQueue& Q, int e) {
	QueuePtr p = (QueuePtr)malloc(sizeof(Qnode));
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return;
}

出队

void DeleteQueueLink(LinkQueue& Q, int& e) {
	QueuePtr p = (QueuePtr)malloc(sizeof(Qnode));
	p = Q.front->next;
	e = p->data;
	Q.front->next = p->next;
	if (Q.rear == p) {
		Q.rear = Q.front;
	}
	free(p);
	return;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值