数据结构(队列的实现)

目录

队列

队列的定义

队列的实现

创建队列的结构

队列的初始化

进行插入数据

删除数据

计算个数

 判断是否为空

返回队列头部数据

返回队列尾部数据


队列

队列的定义

队列是:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。

队列的实现

队列也可以数组和链表的结构实现

使用数组实现队列
优点:

        数组在内存中是连续存储的,因此可以通过索引快速访问任意位置的元素。
在某些情况下,如果数组的大小预先确定或增长预测准确,则可以使用较少的内存。


缺点:

        当队列在数组的一端进行插入(队尾)和删除(队头)操作时,如果数组已满或接近满,可能需要移动大量元素以维护队列的连续性,这会导致较高的时间复杂度(特别是删除操作)。
动态数组,虽然可以自动调整大小,但每次扩容都可能涉及大量元素的复制,这也可能带来性能问题。

使用链表实现队列
优点:

        链表的节点在内存中是动态分配的,不需要连续的存储空间,因此插入和删除操作只需要修改指针,时间复杂度为O(1)。
链表不需要像数组那样预留额外的空间以避免扩容操作,因此在动态数据结构中更加灵活。
缺点:

        链表中的每个节点都需要额外的空间来存储指针,这可能会增加内存消耗。
由于链表在内存中是分散的,所以遍历链表通常比遍历数组慢(尽管对于队列来说,这通常不是问题,因为队列的主要操作是插入和删除)

 因为对于队列来说,使用链表进行头删和尾插比较方便,所以我选择链表。当然顺序表也可以。

创建队列的结构

typedef struct QueueNode
{
	struct QueueNode* next;
	QDatatype data;
}QNode;

typedef struct queue
{
	QNode* head;
	QNode* tail;
	int size;
}queue;

首先创建一个结构体,结构体要连接,所以创建一个结构体指针,然后创建一个储存数据的类型( QDatatype),这个类型是typedef对int类型起的别名,若想更改储存数据类型,可以直接更改。

因为要进行先进先出,所以要找头和尾
所以创建了两个指针,多个数据用结构体创建

head表示创建的头节点

tail表示创建的尾节点

size表示存储的数字个数

队列的初始化

//进行初始化
void QueueInit(queue* pq)
{
	assert(pq);
	pq->tail = pq->head = NULL;
	pq->size = 0;
}

初始全赋值为NULL

存储的数字个数为0;

进行插入数据

//插入数据
void QueuePush(queue* pq, QDatatype x)
{
	assert(pq);
	QNode * newdata = (QNode *)malloc(sizeof(QNode));
	if (newdata==NULL)
	{
		perror("malloc");
		return;
	}
	if (pq->head == NULL)
	{
		assert(pq->tail==NULL);
		pq->tail = newdata;
		pq->head = newdata;
	}
	else
	{

		pq->tail->next = newdata;
		pq->tail = newdata;
	}
	newdata->next = NULL;
	newdata->data = x;
	pq->size++;
}

首先,要插入数据,就要进行开辟空间,这里使用的malloc进行开辟空间,如果开辟失败会进行打印错误并返回,

然后判断是否为第一个插入的数据,插入的第一个数据要进行处理;

如果不为空,尾节点向下进行互换;

size+1;

插入数据相当于是对链表的尾插

删除数据

//删除数据
void QueuePop(queue* pq)
{
	assert(pq);
	assert(pq->head);
	QNode* node = pq->head;
	if (pq->head == pq->tail)
	{	
		pq->tail = NULL;
		pq->head = NULL;
	}
	else
	{
		pq->head = pq->head->next;
	}
	pq->size--;
	free(node);
	node = NULL;
}

首先要判断删除数据前是否只剩下一个节点,如果为一个节点,则头尾节点全部置空;

如果不是,则头节点被下一个节点替换

计算个数

//计算个数
int QueueSize(queue* pq)
{
	assert(pq);
	return pq->size;
}

直接返回size即可

 判断是否为空

//判断是否为空
bool QueueEmpty(queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

返回队列头部数据

//对头数据
QDatatype QueueFront(queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}

返回队列尾部数据

//对尾数据
QDatatype QueueBack(queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}

 

总体来说对应队列,比较容易理解,比较难理解的是他需要创建两个结构体,这个和之前的很不一样,一个拥有存放数据和连接,一个拥有记录数据。

代码连接

queue · 菠萝耿才宏/新数据结构 - 码云 - 开源中国 (gitee.com)icon-default.png?t=N7T8https://gitee.com/pineapple-geng-caihong/new-data-structure/tree/master/queue

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值