数据结构:队列(C语言描述)

本文详细介绍了循环队列的概念、存储结构及其在解决顺序队列假溢出问题上的应用。通过实例展示了循环队列的初始化、队空队满判断、数据入队、出队、获取队头数据、输出队列以及清空队列的操作。循环队列使用循环数组,避免了顺序队列的空间浪费,提高了存储效率。
摘要由CSDN通过智能技术生成

目录

前言

根据存储结构划分队列的种类

循环队列结构体及宏定义如何定义

循环链表的初始化以及判断队空队满

数据入队、数据出队

获取队头数据、输出队列、清空队列

主函数测试


前言

主要内容:循环队列的初始化、队满队空的判断、数据出队、数据入队等操作,根据存储结构划分队列的种类。(如有错误,还望指正) 

队列也是线性表的一种,于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。生活中的队列我们可以看成排队(当然这里不包括插队)。

队列的种类和写法有很多种,本文主要讲解循环队列。其实各种种类的队列写法思路都是大同小异。

根据存储结构划分队列的种类

(1)顺序队列:使用数组作为存储结构,通过出队操作将数据弹出队列后,front之前的空间不能再次得到,浪费空间,会出现假溢出。

(2)循环队列:使用循环数组作为存储结构,将普通数组换成循环数组。在循环数组中,末尾元素的下一个元素不是数组外,而是数组的头元素。

(3)链式队列:单链表实现,动态分配内存避免假溢出的同时还可以延长队列。

(4)双端队列:双端队列两端都可以删除元素和追加元素的线性结构。可以很灵活的实现队列操作也可以实现栈操作,双端队列可以用双向链表实现。

循环队列结构体及宏定义如何定义

循环队列规定了一个存储空间,会出现队满的情况,循环队列解决了顺序队列假溢出的情况。这里就牵扯了到了一个问题,什么是假溢出?随着队头出队,慢慢地就会空出一个个存储单元,队尾一直在进,队头指针无法回退回去,最后就是存储空间根本没用满,但是队列提示已经满了的情况。

#include<stdio.h>
#include<stdlib.h>
#define MAX 10
typedef int Typement;
typedef struct queue{

	Typement array[MAX];
	int front;//指向头节点 
	int rear;//指向尾节点 
	
}QE;

循环链表的初始化以及判断队空队满

为了防止出现假溢出我们判断队满的时候选择牺牲一个空间实现循环队列。所以这一个队列相当于长度为9的队列。当头节点和为节点指向相同坐标时,队列为空。当尾节点加1取模MAX等于头节点的坐标时,队列为满。

void InitQueue(QE *Queue){//初始化队列 
	
	Queue->front=0;//刚开始队列无数据头节点和尾节点指向0 
	Queue->rear=0;
}

int IsEmptyQueue(QE *Queue){//判断队列是否为空,为空返回1,不为空返回0. 
	
	if(Queue->rear==Queue->front){//front始终指向0,当rear==front的时候说明队列为空。
		printf("队列为空,无法操作!\n");
		return 1; 
		}
	else return 0; 
		
}
 
int IsFullQueue(QE *Queue){//判断队列是否已满,已满返回1,未满返回0. 
	
	if((Queue->rear+1)%MAX==Queue->front){//牺牲了一个空间解决了假溢出情况
    //这里的加1再取模如果到了边界就又回到了起点   (9+1)%10=0
		printf("队列已满,无法操作!\n"); 
		return 1;
	} 
	else return 0;
	
}

数据入队、数据出队

理解了解决假溢出的办法之后,就很容易理解入队出队当中尾节点和头节点加1取模的含义了。这就相当于形成了一个循环,到达规定的最大值就取模返回到起点。值得注意的是,入队出队时我们首先应当判断队列的情况,是否为空,是否已满。为空不得出队,已满不得入队。

void PushQueue(QE *Queue,Typement data){//数据入队 
	
	if( !IsFullQueue(Queue) ){
		Queue->array[Queue->rear]=data;//加入数据 
		Queue->rear=(Queue->rear+1)%MAX; //节点后移一位 
	}
		
} 

void PopQueue(QE *Queue){//数据出队 
	
	if( !IsEmptyQueue(Queue) ){
		Queue->front=(Queue->front+1)%MAX;//头节点后移一位 
	
	} 
		
}

获取队头数据、输出队列、清空队列

这些操作就相对简单了,输出队列时我们相当于利用了队空的判断条件,front==rear。只要两者不相等,就还没有输出完全。

Typement GetQueue(QE *Queue){//获取队头数据
	
	if( !IsEmptyQueue(Queue) ){
		return Queue->array[Queue->front];
	}
	
}

void ShowQueue(QE *Queue){//输出队列数据 
	
	if(Queue->front==Queue->rear){
		printf("队列为空,无数据。");
		return; 
	} 
	printf("当前队列数据为:");
	int i=Queue->front;
	while(i!=Queue->rear){
		printf("  %d  ",Queue->array[i]);
		i=(i+1)%MAX;
	}
	printf("\n"); 
}

void DelQueue(QE *Queue){//清空队列 
	Queue->rear=Queue->front;
}

主函数测试

int main(){
	 
	QE *TextQueue=(QE*)malloc(sizeof(QE)); 
	
	//初始化队列
	InitQueue(TextQueue);
	
	//数据入队
	PushQueue(TextQueue,1);
	PushQueue(TextQueue,2);
	PushQueue(TextQueue,3);
	PushQueue(TextQueue,4);
	PushQueue(TextQueue,5); 
	PushQueue(TextQueue,6);
	PushQueue(TextQueue,7);
	PushQueue(TextQueue,8);
	PushQueue(TextQueue,9);
	
	//获取队头数据 
	printf("当前队头数据:%d\n",GetQueue(TextQueue));
	
	//输出队列
	ShowQueue(TextQueue); 
		
	//数据出队
	PopQueue(TextQueue);		
	PopQueue(TextQueue);
	PopQueue(TextQueue);	
	PopQueue(TextQueue);
	PopQueue(TextQueue);		
	PopQueue(TextQueue);
	printf("当前队头数据:%d\n",GetQueue(TextQueue));
	ShowQueue(TextQueue);
		
	//清空队列 
	DelQueue(TextQueue); 
	ShowQueue(TextQueue);
	
	return 0;
} 

测试结果

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算不出来没办法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值