数据结构之基础—队列

本文介绍了队列这一数据结构,源于现实生活中的排队现象,队列具有先进先出的特点。队列可以用链表或数组实现,文中重点讨论了如何利用循环数组高效实现队列。循环数组通过front和rear指针操作,使得元素按照预设顺序排列。当rear达到数组末尾,通过取模操作回到数组开头;同样,当front到达末尾,也会取模回移。文章提供了相关的代码实现,指出队列容量应考虑额外的队尾标记位置。
摘要由CSDN通过智能技术生成

转自:http://blog.csdn.net/thefutureisour/article/details/7835273

前言:

        队列是从现实的“排队”现象中抽象出来的:新来的只能排在队伍的最后面,当你完成的自己事情,就可以离开队列,不能插队。队列是一种特殊的线性结构,它只能在这个结构的一端插入元素,在另一端删除元素。这两端分别称为队首和队尾。
       当我们一看到要频繁的插入、删除元素,第一反应就是中链表实现。的确,在原有链表的基础上,稍作改动,就能把它变成一个队列。但是,程序员们想出了一个更加巧妙地办法,利用数组,准确的说,是循环数组,来方便而快速的实现队列。
      循环数组的原理其实也并不复杂,举一个例子就明白了:假设我们有a0,a1,a2,a3这4个元素组成循环数组,并有front和rear两个标记指向队列的队首和队尾。当我们将0~2这3个元素依次入队后,有:a0 = 0,a1 =1,a2 =2。且front指向a0,rear指向a3。当我们让a0出队时,并不像以前那样,通过左移a0后面的元素拉完成,而是让front指向a1,当我们在让一个3入队时,a3=3,rear指向a0.如果再让a1出队,则front指向a2,如果让5入队,则a0 = 5;rear指向a2(我感觉是a1)。   

       概括的说,所谓的循环队列,完全是概念上YY出来的,我们还是用一般的数组来实现的,但是通过front和rear两个标记,是得队列按照我们事先设定的顺序排列出来。每当给队尾增加一个元素时,rear+1;但是如果rear已经指向数组的最后一个位置,那么通过取模的办法,可以让他跳转到第一个位置(如果这个位置不被队首元素占据的话)。每次出队时,front+1,同样的,如果front已经到了数组的最后,可以通过取模的办法让他跳转到数组的第一个。


代码:

#include <stdio.h>  
#include <malloc.h>

typedef int ElemType;
typedef struct Queue
{
	ElemType *data;
	int front;
	int rear;
	int Qsize;
}Queue;
//1.初始化通过参数传进来创建队列的大小  
bool initQueue(Queue *q, int size)
{
	q->front = 0;
	q->rear = 0;
	q->Qsize = size;
	q->data = (ElemType*)malloc(size*sizeof(ElemType));  
	if (q->data == NULL)
		return false;
	return true;
}
//2.清空队列 
void clearQueue(Queue *q)
{
	q->front = 0;
	q->rear = 0;
}
//3.判断队列是否为空
//队列为空:q->front ==q->rear
//队列为满:(q->rear+1)%q->Qsize==q->front
bool EmeptyQueue(Queue *q)
{
	if (q->front == q->rear)
	{
		printf("queue is empty !");
		return true;
	}
	else if ((q->rear + 1) % q->Qsize == q->front)
	{
		printf("queue is not empty !");
		return false;
	}
}
//4.返回队首元素 
bool getHead(Queue *q, ElemType *e)
{
	if (EmeptyQueue(q))
	{
		printf("can not get the head element! \n");
		return false;
	}
	else
	{
		*e = q->data[q->front];//取元素
		return true;
	}
}
//5.返回队列长度:在循环队列中  
int Qlength(Queue *q)
{
	return (q->rear - q->front + q->Qsize) % q->Qsize;
}
//6.入队
bool enQueue(Queue *q, ElemType e)
{
	//如果队列已满,重新分配内存  
	if (q->rear == q->Qsize - 1)
	{
			q->data = (ElemType*)realloc(q->data, 2 * q->Qsize*sizeof(ElemType));
			if (q->data == NULL)
				return false;
			else
				q->Qsize *= 2;
		
	}
	//先赋值,然后队尾循环加1  
	q->data[q->rear] = e;
	q->rear = (q->rear + 1) % q->Qsize;
	return true;
}
//7.出队
bool deQueue(Queue *q, ElemType *e)
{
	if (EmeptyQueue(q))
		return false;
	else
	{
		*e = q->data[q->front];
		//队首标记循环加1  
		q->front = (q->front + 1 + q->Qsize) % q->Qsize;
	}
	return true;
}


说明:

      我在定义时,专门定义了队列的容量,以防止不停的放里面加入元素时越界情况的发生。还有一点需要注意,当我定义了5个长度的队列时,实际能用的只有4个,另外一个供队尾标记使用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值