数据结构----队列

1. 队列的定义

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

 2. 队列的实现

        队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

typedef int QDataType;
typedef struct QueueNode
{
	struct QNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;


//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestory(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//返回队列首元素
QDataType QueueFront(Queue* pq);
//返回队尾元素
QDataType QueueBack(Queue* pq);
//返回队列长度
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);

        以上是本次要学习的一些队列的操作, 需要注意的是, QueueNode指的是队列中每个结点, 都有一个data存放数据, 一个next指向下一个结点, 而Queue代表的就是这个队列了, 有两个指针, 分别指向队列的头和尾, 还有一个size记录队列的大小

2.1 队列初始化

//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

        很简单, 就是将队列进行初始化

2.2 入队列

//入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	//创建一个新结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	//第一次插入需要特殊处理
	if (pq->size == 0)
	{
		pq->phead = newnode;
		pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;

}

        入队列实际就是将新节点插入尾指针的后面, 因为此次使用的是不带头的单链表, 所以第一次入队列需要特殊处理, 即对头指针进行修改

 2.3 出队列

//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	//一个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* del = pq->phead;
		pq->phead = pq->phead->next;
		free(del);
	}

	pq->size--;
}

        和插入一样, 需要对只有一个结点的情况特殊处理, 将phead和ptail置空, 防止出现野指针的情况, 还需要判断队列是否为空, 如果为空则删除失败

 2.4 返回队首元素

//返回队列首元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->phead->data;
}

        很简单, 只要队列不为空, 直接返回phead指向的结点的data就可以了

2.5 返回队尾元素

//返回队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->ptail->data;
}

        和上面一个道理

2.6 返回队列长度

//返回队列长度
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

        前面记录下队列的长度在这里就用到了

2.7 判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL
		&& pq->ptail == NULL;
}

        也很简单那, 当phead和ptail同时为空的时候, 队列就是空, 此时返回true, 如果不同时为空, 则返回false, 也可以使用size来判断队列是否为空

2.8 队列的销毁

//队列销毁
void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur != NULL)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

        队列中每个结点都是单独malloc出来的, 所以不能一次性全部释放掉, 应该设置一个cur指向这个队列, 从队头开始向队尾, 一个结点一个结点的释放


完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>


typedef int QDataType;
typedef struct QueueNode
{
	struct QNode* next;
	QDataType data;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;


//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestory(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//返回队列首元素
QDataType QueueFront(Queue* pq);
//返回队尾元素
QDataType QueueBack(Queue* pq);
//返回队列长度
int QueueSize(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);


//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);

	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}


//队列销毁
void QueueDestory(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur != NULL)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}


//入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	//创建一个新结点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	//第一次插入需要特殊处理
	if (pq->size == 0)
	{
		pq->phead = newnode;
		pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;

}


//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	//一个结点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* del = pq->phead;
		pq->phead = pq->phead->next;
		free(del);
	}

	pq->size--;
}


//返回队列首元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->phead->data;
}


//返回队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(&pq));

	return pq->ptail->data;
}


//返回队列长度
int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}


//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->phead == NULL
		&& pq->ptail == NULL;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值