数据结构——队列

1、队列概念前端

队列时一种特殊的线性表,只容许在表的前端进行删除操做,而在表的后端进行插入操做,队列具备先进先出的特色。后端

队列的操做很简单,主要有如下几种常见的操做:指针

(1)初始化队列:建立一个队列code

(2)进队列:将一个元素添加到队尾队列

(3)出队列:将队头元素取出,同时删除该元素,使下一个元素成为对头内存

(4)获取队列第一元素:将队头元素取出,不删除该元素it

(5)获取队列长度:根据队头和队尾计算出队列中元素的数量class

 

2、顺序队列实现循环

    将队列用顺序存储方式保存时,在内存中申请一片区域用来保存元素,当第一个元素A进入队列时,因是空列队,所以元素A将排在队头,接着B、C、D顺次进入队列,就获得如图所示的队列。其中head指向队头,以指示队头元素出队操做,tail指向队尾,以指示新增元素进入队列。以下图所示:im


    执行一次出队操做,元素A将出队,这时第2个元素B将成为队头,head指针将指向该元素若是要将元素E入队,则是将其放入tail指针指向元素的后一个位置(以下图为5的单元),并使tail指针指向序号为5的单元。

(1)定义顺序队列的结构

#define QUEUEMAX 15

typedef struct{
	DATA data[QUEUEMAX];
	int head;
	int tail;
} SeqQueue;

(2)初始化队列

SeqQueue *SeqQueueInit()
{
	SeqQueue *q;
	if (q=(SeqQueue *)malloc(sizeof(SeqQueue))) {
		q->head = 0;
		q->tail = 0;
		return q;
	}

	return NULL;
}

(3)释放队列

void SeqQueueFree(SeqQueue *q)
{
	if (q)
		free(q);
}

(4)获取队列状态

/*
*判断队列是否为空
*/

int SeqQueueIsEmpty(SeqQueue *q)
{
	return (q->head == q->tail);
}

/*
*判断队列是否已满
*/
int SeqQueueIsFull(SeqQueue *q)
{
	return (q->tail == QUEUEMAX);
}

/*
*获取队列的长度
*/
int SeqQueueLen(SeqQueue *q)
{
	return (q->tail - q->head);
}

(5)入队操做

int SeqQueueIn(SeqQueue *q, DATA data)
{
	if (SeqQueueIsFull(q)) {
		printf("队列已满!\n");
		return 0;
	}

	q->data[q->tail++] = data;
	return 1;
}

(6)出队操做

DATA *SeqQueueOut(SeqQueue *q)
{
	if (SeqQueueIsEmpty(q)) {
		printf("队列已空!\n");
		return NULL;
	}

	return &(q->data[q->head++]);
}

(7)获取队头元素

DATA *SeqQueuePeek(SeqQueue *q)
{
	if (SeqQueueIsEmpty(q)) {
		printf("队列已空!\n");
		return NULL;
	}

	return &(q->data[q->head]);
}

3、循环队列

    因为每次出队后,队头的指针都向后移动,这时候就会出现一个问题,就是假溢出。以下图所示:

tail已指向队尾,这时进行入队操做时,虽然前面还有空位置,但仍然显示队列已满。为了解决这个问题,就提出了循环队列。

循环队列就是将队列的首尾相连构成一个环形区域,当在第n个位置进行元素的入队操做后,下一个地址就翻转为1

循环队列结构图:

在循环队列中,主要须要计算队尾tail和队头head的序号

以入队操做为例:

一、将队尾序号加1,即tail=tail+1

二、若tail=n+1,则tail=1

其实前2步,可使用表达式tail=(tail+1)%n

三、若head=tail,即队尾和队头重合了,表示队列已满提示队列溢出

四、若未溢出,将元素入队便可

(1)定义循环队列的结构 

#define QUEUEMAX 15

typedef struct{
	DATA data[QUEUEMAX];
	int head;
	int tail;
} CycQueue;

(2)初始化队列

CycQueue *CycQueueInit()
{
	CycQueue *q;
	if (q=(CycQueue *)malloc(sizeof(CycQueue))) {
		q->head = 0;
		q->tail = 0;
		return q;
	}

	return NULL;
}

(3)释放队列

void CycQueueFree(CycQueue *q)
{
	if (q)
		free(q);
}

(4)获取队列状态

/*
*判断队列是否为空
*/

int CycQueueIsEmpty(CycQueue *q)
{
	return (q->head == q->tail);
}


/*
*判断队列是否已满
*/
int CycQueueIsFull(CycQueue *q)
{
	return ((q->tail+1)%QUEUEMAX == q->head);
}


/*
*获取队列的长度
*/
int CycQueueLen(CycQueue *q)
{
	int n;
	n = q->tail - q->head;
	if (n < 0) {
		n = QUEUEMAX + n;
	}
	return n;
}

(5)入队操做

int CycQueueIn(CycQueue *q, DATA data)
{
	if (CycQueueIsFull(q)) {
		printf("队列已满!\n");
		return 0;
	}
	q->tail = (q->tail+1)%QUEUEMAX;
	q->data[q->tail] = data;
	return 1;
}

(6)出队操做

DATA *CycQueueOut(CycQueue *q)
{
	int head;

	if (CycQueueIsEmpty(q)) {
		printf("队列已空!\n");
		return NULL;
	}

	head = q->head;
	q->head = (q->head +1)%QUEUEMAX;
	return &(q->data[head]);
}

(7)获取队头元素

DATA *CycQueuePeek(CycQueue *q)
{
	if (CycQueueIsEmpty(q)) {
		printf("队列已空!\n");
		return NULL;
	}
	return &(q->data[q->head]);
}
相关文章
相关标签/搜索