欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构之队列

程序员文章站 2022-05-04 15:58:00
...

什么是队列?

队列(queue)是一种先进先出(FIFO)的数据结构。就如生活中排队一样,先排的人在队伍的最前面,后排的人在队伍的最后面。

数据结构之队列

队列的实现方式

队列的实现方式分为数组和链表两种

数组的方式实现队列需要两个指针,指向对头的front,指向队尾的rear。由于队列是对的头部删除,队的尾部插入数据,当我们在删除数据之后,数据并不会自动去补齐前面已经删除的空白的位置,这就导致有的时候整个数组并没有多少元素,但是已经不能插入数据了。从而造成资源的浪费!如果在元素出队的过程中,不断地移动元素,这样复杂所需资源非常大,也是不好的实现方法。这个时候,我们找到了另外一种实现方法:循环数组

数据结构之队列

如下图所示,就是典型的循环数组的样子。左边为空循环队列,右边为满循环队列。但是我们仅仅用rear==front是无法判断这个队列是否是满还是空的,一般我们有两种方法,第一种是引入一个新变量,来记录队列元素的个数,插入元素加1,删除元素减1,清空队列就置0;另外一种就是定义“满”的含义,在数组中定义一个元素始终不使用,当队列满的时候,front和rear的值就不可能相同了。

当我们采用第二种方法时,我们让rear比front小1,这样就可以解决问题了。

当满足下面条件时,队列为空:(rear+1)%QUEUE_SIZE== front

当满足下面条件时,队列为满:(rear+2)%QUEUE_SIZE== front

数据结构之队列

队列还有如下的链式存储方式,也就是只允许头进尾除的线性表中只允许头进尾除的单链表。

数据结构之队列

队列的接口

#include<stdlib.h>

#define QUEUE_TYPE int     //定义队列元素类型

void create_queue(size_t size);   //创建一个队列,参数指定队列可以存储的元素的最大数量。适用于动态分配数组的队列

void destory_queue(void);   //销毁一个队列,适用于链式和动态分配数组的队列

void insert_queue(QUEUE_TYPE value);  //向队列中添加一个新元素

void delete_queue(void);  //移除一个元素并丢弃

QUEUE_TYPE first(void);    //返回队列的第一个元素的值

int is_empty(void);      //判断队列是否为空

int is_full(void);         //判断队列是否已满


队列的实现

静态数组实现循环队列

#include “queue.h”
#include <stdio.h>
#include <assert.h>

#define QUEUE_SIZE   100
#define ARRAY_SIZE    (QUEUE_SIZE + 1)

static QUEUE_TYPE queue[ARRAY_SIZE];
static size_t front = 1;
static size_t rear = 0;

void insert_queue(QUEUE_TYPE value){
assert(is_full());
rear = (rear+1)%ARRAY_SIZE;
queue[rear] = value;
}

void delete(void){
assert(is_empty());
front = (front + 1)%ARRAY_SIZE;
}

QUEUE_TYPE first(void){
assert(!is_empty());
return queue[front];
}

int is_empty(void){
    return (rear + 1) % ARRAY_SIZE == front;
}

int is_full(void){
    return (rear + 2) & ARRAY_SIZE == front;
}

动态数组实现队列

相较于静态数组,动态数组的主要区别在与初始化队列时:


void InitQueue(int size){
maxSize = size
queue = (int *)malloc(size *sizeof(int));
front = 1;
rear = 0;
}

链式队列实现

数据结构之队列

//单链队列使用链表作为基本数据结果,所以不存在伪溢出的问题,队列长度也没有限制。但插入和读取的时间代价较高  
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<stdbool.h>

#define TRUE 1
#define FALSE 0

typedef char QElemType;

/*单链队列——队列的链式存储结构*/
typedef struct QNode
{
	QElemType data;
	struct QNode *next;
}QNode,*QueuePtr;

typedef struct
{
	QueuePtr front;  /*队头指针*/
	QueuePtr  rear;  /*队尾指针*/
}LinkQueue;

LinkQueue Q;

int  InitQueue(LinkQueue *Q) 
{ /*构造一个空队列Q*/ 
	Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode)); 
	if(!Q->front){
		printf("ERROR!\n");
		return FALSE;
	}
	Q->front->next=NULL;
	return TRUE;
}

int DestroyQueue(LinkQueue *Q) 
{ /*销毁队列Q(无论空否均可)*/ 
	while(Q->front)
	{
		Q->rear=Q->front->next;
		free(Q->front);
		Q->front=Q->rear;
	}
	return TRUE;
}

void ClearQueue(LinkQueue *Q) 
{ /*将Q清空为空队列*/ 
	QueuePtr p,q; 
	Q->rear=Q->front; 
	p=Q->front->next; 
	Q->front->next=NULL; 
	while(p)
	{
		q=p;
		p=p->next;
		free(q);
	}
}

bool  is_Empty(LinkQueue Q) 
{ /*若Q为空队列,则返回TRUE,否则返回FALSE*/ 
	if(Q.front->next==NULL) 
		return TRUE; 
	else 
		return FALSE; 
}	
	
int QueueLength(LinkQueue Q) 
{ /*求队列的长度*/ 
	int i=0; 
	QueuePtr p; 
	p=Q.front; 
	while(Q.rear!=p) 
	{ 
		i++; 
		p=p->next; 
	} 
	return i;	
}	
 
bool  GetHead_Q(LinkQueue Q,QElemType *e) 
{ /*若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR*/ 
	QueuePtr p; 
	if(Q.front==Q.rear) {
		printf("IS empty\n");
		return;
	}
	p=Q.front->next; 
	*e=p->data; 
	return TRUE; 
} 
	
int  InsertQueue(LinkQueue *Q,QElemType e) 
{ /* 插入元素e为Q的新的队尾元素*/ 
	QueuePtr p=(QueuePtr)malloc(sizeof(QNode)); 
	if(!p) { /*存储分配失败*/
		printf("存储分配失败\n");
		return FALSE;
	}
	p->data=e; 
	p->next=NULL; 
	Q->rear->next=p; 
	Q->rear=p; 
	return TRUE;
} 
 
int DeleteQueue(LinkQueue *Q,QElemType *e) 
{ /*若队列不空,删除Q的队头元素,用e返回其值,并返回TRUE,否则返回ERROR*/ 
	QueuePtr p; 
	if(Q->front==Q->rear) 
		return FALSE; 
	p=Q->front->next; 
	*e=p->data; 
	Q->front->next=p->next; 
	if(Q->rear==p) 
		Q->rear=Q->front; 
	free(p); 
	return TRUE; 
} 

int QueueTraverse(LinkQueue *Q) 
{ /*遍历队列Q*/ 
	QueuePtr p;
	if(Q->rear == Q->front)
		return FALSE;
	p = Q->front->next;
	printf("the queue is:");
	while(p){
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");
    return TRUE; 
} 

int main(int argc,char *argv[]){
	LinkQueue Q;
	InitQueue(&Q);
	QElemType e;
	printf("please input elem:\n");
	while((e = getchar())!='\n'){
		if(e == ' ')
			continue;		
		InsertQueue(&Q,(e-0X30));
	}
	printf("output:\n");
	QueueTraverse(&Q);
	
}

参考文档:

https://www.cnblogs.com/kubixuesheng/p/4104802.html

http://blog.csdn.net/juanqinyang/article/details/51354293

http://blog.csdn.net/leichelle/article/details/7546775

《C与指针》