队列的介绍和实现(C语言实现)

Posted 可乐不解渴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了队列的介绍和实现(C语言实现)相关的知识,希望对你有一定的参考价值。

人书就像骑自行车,想要保持平衡就得往前走。

队列的概念

队列是限制元素插入操作固定在一端进行,而结点的删除操作固定在另一端进行的线性表.队列犹如一个两端开口的管道。允许插入的一端称为队头,允许删除的一端称为队尾。队列的特点是结点在队列中的排队次序和出队次序按进队时间先后确定,即先进队者先出队。因此,队列又称先进先出表.简称FIFO(first in first out)表.

队列的结构

队列的实现

在之前我们实现的栈中,我们是用顺序表实现的。而今天的队列我们用链表来实现,为什么不用顺序表来实现队列呢?这是因为我们的队列要进行队头出元素队尾进元素,如果是顺序表你频繁的去删除第一个元素,那么我们要将后面的元素频繁的往前挪动数据,导致效率变低。在下面我们就来实现队列。

队列的初始化

在初始化之前我们需要创建一个结点类型,类型包含了该队列每个结点的数据和指向下一结点的指针。

typedef int QueueDataType;
typedef struct QueueNode
{
	//数据域
	QueueDataType _data;
	//指针域,指向下一个结点
	struct QueueNode* _next;
}QueueNode;

我们知道队列与普通链表又有所不同,队列的基本信息要包括了队头和队尾,因为我们要进行头部出元素,尾部入元素。所以我们需要再创建一个结构体用于存放队列的队头队尾

typedef struct Queue
{
	//队头指针
	QueueNode* _head;

	//队尾指针
	QueueNode* _tail;
}Queue;

最后当我们创建一个队列的对象时,我们需要将这个Queue的队头与队尾进行初始化。

//初始化
void QueueInit(Queue* pQ)
{
	assert(pQ != NULL);
	pQ->_head = NULL;
	pQ->_tail = NULL;
}

队列的销毁

有初始化那么必定就会有销毁,因为我们的队列的结点都是动态开辟出来的,我们需要将每一个结点去删除。

//销毁
void QueueDestory(Queue* pQ)
{
	assert(NULL != pQ);
	
	while (NULL != pQ->_head)
	{
		QueueNode* next = pQ->_head->_next;
		free(pQ->_head);
		pQ->_head = next;
	}
	pQ->_head = NULL;
	pQ->_tail = NULL;
}

入队

在上面的概念中我们说到过,队列是一个先进先出的。这就好比我们去吃饭排队取号一样,取得号是前面的号数+1,并将你排队的信息插入到尾部。我们这里的入队同样是从尾部插入的。

//入队
void QueuePush(Queue* pQ, const QueueDataType x)
{
	assert(NULL != pQ);
	//创建一个新的结点,并赋予值
	QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
	if (newNode == NULL)
	{
		printf("分配空间失败\\n");
		exit(-1);
	}
	else
	{
		newNode->_data = x;
		newNode->_next = NULL;
	}


	if (pQ->_head == NULL)
	{
		pQ->_head = pQ->_tail = newNode;
	}
	else
	{
		pQ->_tail->_next = newNode;
		pQ->_tail = newNode;
	}
}

出队

出队操作这里就好比你现在去吃饭,并且取到的号是1号,那么下一个就是你进去了,进去后的同时删除掉你排队的信息。同样出队,就是从头发删除掉一个元素。

//出队
void QueuePop(Queue* pQ)
{
	assert(pQ!=NULL);
	assert(pQ->_head != NULL);
	QueueNode* next = pQ->_head->_next;
	free(pQ->_head);
	pQ->_head= next;
	if (pQ->_head == NULL)
	{
		 pQ->_tail = NULL;
	}
}

获取队头元素

获取队列头部元素,即返回队头指针指向的数据即可。

//取队头元素
QueueDataType QueueFront(Queue* pQ)
{
	assert(pQ != NULL);
	assert(pQ->_head != NULL);
	return pQ->_head->_data;
}

获取队尾元素

获取队列尾部元素,即返回队尾指针指向的数据即可。

//取队尾元素
QueueDataType QueueBack(Queue* pQ)
{
	assert(pQ != NULL);
	assert(pQ->_tail != NULL);
	return pQ->_tail->_data;
}

判断队列是否为空

检测队列是否为空,即判断队头指针指向的内容是否为空。

//判断队是否为空,true表示队为空,false表示队不空
bool QueueEmpty(Queue* pQ)
{
	assert(pQ != NULL);
	if (pQ->_head == NULL)
	{
		return true;
	}
	return false;
}

查看队列中的元素个数

该函数不建议经常使用,因为我们每次使用时,都是从头部去依次遍历到尾部。时间复杂度为O(n)。如果频繁的需要知道队列的元素个数时,不妨在队列的结构体中增加一个元素个数的变量来记录当前元素的个数。

//队中元素得个数
int QueueSize(Queue* pQ)
{
	assert(pQ != NULL);
	QueueNode* cur = pQ->_head;
	int size = 0;
	while (cur!=NULL)
	{
		size++;
		cur = cur->_next;
	}
	return size;
}

以上是关于队列的介绍和实现(C语言实现)的主要内容,如果未能解决你的问题,请参考以下文章

c 语言数据结构栈和队列的相关操作

《线性表的插入和删除算法实现》以及《栈和队列的插入和删除算法实现》的c语言代码

手把手教你c语言队列实现代码,通俗易懂超详细!

C语言实现使用动态数组实现循环队列

数据结构之队列(Java语言描述)

新手向C语言实现特殊数据结构——队列(含用两个队列实现栈)