【数据结构】队列的定义及实现(c语言)

队列的定义:

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列的顺序存储实现:

队列的顺序存储通常由一个一维数组,一个记录队头的变量front,一个记录队尾的变量rear和一个记录队列大小的变量 MaxSize组成。结构如下:

#define QDataType int 
typedef struct Queue{//队列的结构
	QDataType *queue;
	QDataType front;
	QDataType rear;
	QDataType MaxSize;//队列大小
}Queue;

什么是环形队列?
rear指向队头元素,front为队尾元素的下标加一,rear 和 front 的初始值都为0;在实现队列的删除队头操作时,rear变量如何变化呢?如果不改变rear变量的值将队列的其他元素都向前移一位那么操作就很麻烦,所以我们直接让rear变量+1,既指向下一个元素。在实现插入队尾操后时,让front+1,当front 等于 MaxSize -1 时,让front等于 0,这样就形成了环形队列。
值得注意的是 我们如何判断环形链表是空还是满?
假设数组长度为n,队列的长度也为n那么队列满队列空 rear 和front 都相等无法判别。所以数组长度为n,队列的长度只能为 n-1。判定如下

bool is_QueueFull(Queue* q){// 检测队列是否为满
	if(( q ->rear + 1 ) % q ->MaxSize == q ->front ){
		return true;
	}else{
		return false;
	}
}
bool is_QueueEmpty(Queue* q){// 检测队列是否为空
	if(q ->front == q ->rear ){
		return true;
	}else{
		return false;
	}
}

队列的链式存储实现:

队列的链式存储一般不设置队列的大小,它由一个标志队头的元素 front 和一个标志链尾的元素rear组成。初始状态 rear和front都为空。结构如下:

#define QDataType int 
typedef struct Node{//节点结构
	struct Node* next;
	QDataType data;
}Node;
typedef struct Queue{//队列的结构
	Node* front;
	Node* rear;
}Queue;

顺序存储实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define QDataType int 
typedef struct Queue{//队列的结构
	QDataType *queue;
	QDataType front;//指向队头
	QDataType rear;//指向队尾的下一个元素
	QDataType MaxSize;//队列大小
}Queue;
Queue* QueueInit(QDataType MaxSize);// 初始化队列
void QueuePush(Queue* q, QDataType data);// 队尾入队列
void QueuePop(Queue* q);// 队头出队列
bool is_QueueEmpty(Queue* q);// 检测队列是否为空
bool is_QueueFull(Queue* q);// 检测队列是否为满
void QueueDestroy(Queue* q);// 销毁队列
QDataType QueueFront(Queue* q);//获取队列队头元素
QDataType Queuerear(Queue* q);//获取队列队尾元素


Queue* QueueInit(QDataType MaxSize){// 初始化队列
	Queue* q = (Queue*)malloc(sizeof(Queue));
	q ->queue = (QDataType *)malloc(sizeof(QDataType));
	q ->front = q ->rear = 0;
	q ->MaxSize = MaxSize;
	return q;
}

void QueuePush(Queue* q, QDataType data){// 队尾入队列
	if( is_QueueFull(q) ){
		printf("队列满");
	}else{
		q ->queue[( q ->rear ) ++] = data;
		q ->rear = (q ->rear) % (q ->MaxSize);
	}
	
}
void QueuePop(Queue* q){// 队头出队列
	if( is_QueueEmpty(q) ){
		printf("队列空");
	}else{
		q ->front ++;
		q ->front = ( q ->front ) % ( q ->MaxSize);
	}

}
bool is_QueueFull(Queue* q){// 检测队列是否为满
	if(( q ->rear + 1 ) % q ->MaxSize == q ->front ){
		return true;
	}else{
		return false;
	}
}
bool is_QueueEmpty(Queue* q){// 检测队列是否为空
	if(q ->front == q ->rear ){
		return true;
	}else{
		return false;
	}
}
QDataType QueueFront(Queue* q){
	if(is_QueueEmpty(q)){
		printf("队列为空");
	}else{
		return (q ->queue)[q ->front];
	}
}
QDataType Queuerear(Queue* q){//获取队列队尾元素
	if(is_QueueEmpty(q)){
		printf("队列为空");
	}else{
		if( q ->rear == 0){
			return (q ->queue)[(q ->MaxSize) -1 ];
		}else{
			return (q ->queue)[(q ->rear) - 1 ];
		}
	}
}
void QueueDestroy(Queue* q){// 销毁队列
	free(q ->queue);//
	free(q);
}

链式存储实现代码:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define QDataType int 
typedef struct Node{//节点结构
	struct Node* next;
	QDataType data;
}Node;
typedef struct Queue{//队列的结构
	Node* front;
	Node* rear;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
void QueuePush(Queue* q, QDataType data);
// 队头出队列
void QueuePop(Queue* q);
// 获取队列头部元素
QDataType QueueFront(Queue* q);
// 获取队列队尾元素
QDataType Queuerear(Queue* q);
// 检测队列是否为空
bool is_QueueEmpty(Queue* q);
// 销毁队列
void QueueDestroy(Queue* q);

Queue* QueueInit(){//队列初始化
	Queue* q = (Queue*)malloc(sizeof(Queue));
	q ->front = q ->rear =NULL;
	return q;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data){
	assert(q);//队列不存在
	Node* ptr = (Node*)malloc(sizeof(Node));
	ptr ->data = data;
	ptr ->next = NULL;
	if(is_QueueEmpty(q)){//队列为空
		q ->front = q ->rear = ptr;
	}else{
		q ->rear ->next = ptr;
		q ->rear = ptr;
	}
}
// 队头出队列
void QueuePop(Queue* q){
	if(is_QueueEmpty(q)){
		printf("队列空");
	}else{
		Node* ptr = q ->front;
		q ->front =q ->front ->next;
		if(q ->front == NULL){
			q ->rear = q ->front;
		}
		free(ptr);
	}
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool is_QueueEmpty(Queue* q){
	assert(q);
	if(q ->front == NULL){
		return  true;
	}else{
		return false;
	}
}
// 获取队列头部元素
QDataType QueueFront(Queue* q){
	assert(q);
	if(is_QueueEmpty(q)){
		printf("队列空\n");
	}else{
		return q ->front ->data;
	}
}
// 获取队列队尾元素
QDataType Queuerear(Queue* q){
	assert(q);
	if(is_QueueEmpty(q)){
		printf("队列空\n");
	}else{
		return (q ->rear)->data;
	}
}
// 销毁队列
void QueueDestroy(Queue* q){
	assert(q);
	while(!is_QueueEmpty(q)){
		QueuePop(q);
	}
	free(q);
}

#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列的一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针和尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值