【数据结构】C++语言实现队列(详细解读)

9efbcbc3d25747719da38c01b3fa9b4f.gif

 c语言中的小小白-CSDN博客c语言中的小小白关注算法,c++,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm=1001.2014.3001.5343

给大家分享一句我很喜欢我话:

知不足而奋进,望远山而前行!!!

铁铁们,成功的路上必然是孤独且艰难的,但是我们不可以放弃,远山就在前方,但我们能力仍然不足,所有我们更要奋进前行!!!

今天我们更新了队列内容,

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

什么是队列?

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(head)进行删除操作,而在表的后端(tail)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

这个队列就可以理解成我们平时的排队,先进入的先出去,与我们之前实现的先进后出的栈相反。

用什么来实现栈?

再把上次的图拿出来,我们看看是用线性表来实现队列,还是链表比较好❓

由于我们队列中有多少元素不确定,为了方便,我们使用链表,可以做到需要就直接申请,还有一点就是队列是先进先出,顺序固定,不需要随机访问。所以我们这里实现队列使用链表。

队列的实现

头文件:

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

定义结构体:

typedef int QDataType;

typedef struct QueueNode//队列的元素节点
{
	struct QueueNode* next;
	QDataType val;
}QNode;

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

函数声明:

//初始化
void QueueInit(Queue* pq);

//队尾插入
void QueuePush(Queue* pq, QDataType x);

//头删
void QueuePop(Queue* pq);

//获取长度
int QueueSize(Queue* pq);

//队列的销毁
void QueueDestroy(Queue* pq);

//取出队首元素
QDataType QueueFront(Queue* pq);

//取出队尾元素
QDataType QueueBack(Queue* pq);

//判断是否为空
bool QueueEmpty(Queue* pq);

函数的实现:

队列的初始化:

//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

初始化还是比较简单的,就是令这个头和尾都为NULL,size=0。

队列的尾插:

//尾插
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc failed!");
		exit(0);
	}

	newnode->next = NULL;
	newnode->val = x;
	
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail = pq->ptail->next = newnode;

	}
	pq->size++;
}

尾插这里我们要注意分为两种情况,一种就是此时这个队列还为空队列,这时就要令ptail和phead都为newnode,然后若不是,那么我们就只令ptail的下一个点等于newnode,然后ptail指向下一个点。

队列的头删:

//头删
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	//一个节点,防止出现野指针
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;

		pq->size--;
	}
}

头删我们这里也要注意,因为我们这个队列玩意只有一个点,那么我们删除之后可能就会造成ptail为野指针的情况,所以我们这里也要分情况:一种就是如果phead指向NULL,即只有一个节点,所以我们就要free掉phead的同时,还要将两个都置为NULL,另一种情况就只需要关注phead,操作完之后将phead指向下一个点。

获取队列长队:

//获取长度
int QueueSize(Queue* pq)
{
	assert(pq);
	
	return pq->size;
}

这里就是我们前面创建对列要加一个size的原因,这样我们就可以方便的知道队列的大小,否则每次想得到队列的大小都要重新计算一遍,浪费更多的时间。

队列的销毁:

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

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

队列的销毁也没什么好说的,就是创建一个新的队列,然后循环不断free每一个队列点。

获取队尾元素和队首元素:

//获取队首元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead && pq->ptail);//防止为空
	return pq->phead->val;

}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->phead && pq->ptail);
	
	return pq->ptail->val;
}

这个就是先断言一下,然后直接返回对应的值即可。

判断是否为空:

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

	return pq->ptail == NULL;
}

这里直接用bool来判断,是就返回true,否则返回false。

完整代码:

Queue.h

#pragma once
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<stdbool.h>
#include<iostream>

using namespace std;

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}QNode;

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


//初始化
void QueueInit(Queue* pq);

//队尾插入
void QueuePush(Queue* pq, QDataType x);

//头删
void QueuePop(Queue* pq);

//获取长度
int QueueSize(Queue* pq);

//队列的销毁
void QueueDestroy(Queue* pq);

//取出队首元素
QDataType QueueFront(Queue* pq);

//取出队尾元素
QDataType QueueBack(Queue* pq);

//判断是否为空
bool QueueEmpty(Queue* pq);

Queue.cpp:

#include"Queue.h"


//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	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 failed!");
		exit(0);
	}

	newnode->next = NULL;
	newnode->val = x;
	
	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail = pq->ptail->next = newnode;

	}
	pq->size++;
}



//头删
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	//一个节点,防止出现野指针
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;

		pq->size--;
	}
}



//获取长度
int QueueSize(Queue* pq)
{
	assert(pq);
	
	return pq->size;
}


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

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

//获取队首元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead && pq->ptail);//防止为空
	return pq->phead->val;

}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->phead && pq->ptail);
	
	return pq->ptail->val;
}





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

	return pq->ptail == NULL;
}


test.cpp:

#include"Queue.h"

int main()
{
	Queue q;

	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	QueuePop(&q);
	while (!QueueEmpty(&q))
	{
		cout << QueueFront(&q)<<endl;
		QueuePop(&q);
	}

	return 0;
}

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-05-11 18:22:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-11 18:22:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-11 18:22:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-11 18:22:03       20 阅读

热门阅读

  1. MySql 事务

    2024-05-11 18:22:03       8 阅读
  2. 设计模式-工厂模式

    2024-05-11 18:22:03       11 阅读
  3. 【element-plus】自动导入 + typescript 提示

    2024-05-11 18:22:03       10 阅读
  4. 设计模式-原型模式

    2024-05-11 18:22:03       9 阅读
  5. 6. path路径绘制:使用path绘制弧线

    2024-05-11 18:22:03       11 阅读
  6. P1443 马的遍历

    2024-05-11 18:22:03       10 阅读
  7. 设计模式:命令模式

    2024-05-11 18:22:03       10 阅读
  8. 利用干扰源模型确定多通道音频信号盲源分离

    2024-05-11 18:22:03       13 阅读