【数据结构1.0】队列

鼠鼠我呀,今天写一个基于C语言关于队列的博客,如果有兴趣的读者老爷可以抽空看看,很希望的到各位老爷观点和点评捏!

在此今日,也祝各位小姐姐女生节快乐啊,愿笑容依旧灿烂如初阳,勇气与童真永不退色!

目录

1.队列的概念及结构

 2.对列的实现 

2.1.queue.h

2.2.queue.c

2.3.test.c

2.4.定义队列

2.5.初始化队列

2.6.队尾入队列

2.7.对头出队列

2.8.获取队列队头元素

2.9.获取队列队尾元素

2.10.获取队列中有效元素的个数

2.11.检测队列是否为空,如果为空返回非零结果,非空返回0

2.12.销毁队列 

 3.分析运行结果

4.ending


1.队列的概念及结构

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

队尾:进行插入操作的一端称为队尾。

对头:进行删除操作的一端称为队头 。

咱们画一个队列的想象图就很好理解上面几个概念:

其实很好理解,队列里面的数据元素就像排队一样,先进入队列的数据元素当然先出队列了。

 2.对列的实现 

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

而队列用链表实现的方案也是多种多样,只要满足队列的定义即可。鼠鼠我今天写一个方案(本方案基于无头单向非循环链表)各位佬们可以看看啊,俺先把三个文件和运行结果呈现如下:

2.1.queue.h

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


typedef int QDatatype;

typedef struct QNode
{
	QDatatype _data;
	struct  QNode* _next;
}QNode;

typedef struct Queue
{
	int k;
	QNode* head;
	QNode* tail;
}Queue;

//初始化队列
void QueueInit(Queue* q);

//队尾入数据
void QueuePush(Queue* q, QDatatype data);

//对头出数据
void QueuePop(Queue* q);

//获取队列对头元素
QDatatype QueueFront(Queue* q);

//获取队列队尾元素
QDatatype QueueBack(Queue* q);

//获取队列中有效元素个数
int QueueSize(Queue* q);

//检测队列是否为空,如果为空返回非零结果,非空返回0
bool QueueEmpty(Queue* q);

//销毁队列
void QueueDestory(Queue* q);

2.2.queue.c

#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"

void QueueInit(Queue* q)
{
	assert(q);
	q->head = q->tail = NULL;
	q->k = 0;
}

void QueuePush(Queue* q, QDatatype data)
{
	assert(q);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	tmp->_data = data;
	tmp->_next = NULL;
	if (q->tail == NULL)
	{
		q->head = q->tail = tmp;
	}
	else
	{
		q->tail->_next = tmp;
		q->tail = tmp;
	}
	q->k++;
}

void QueuePop(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	QNode* next = q->head->_next;
	free(q->head);
	q->head = next;
	if (q->head == NULL)
	{
		q->tail = NULL;
	}
	q->k--;
}

QDatatype QueueFront(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	return q->head->_data;
}

QDatatype QueueBack(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	return q->tail->_data;
}

int QueueSize(Queue* q)
{
	assert(q);
	return q->k;
}

bool QueueEmpty(Queue* q)
{
	assert(q);
	return q->tail == NULL;
}

void QueueDestory(Queue* q)
{
	assert(q);
	QNode* tmp = q->head;
	while (tmp)
	{
		QNode* next = tmp->_next;
		free(tmp);
		tmp = next;
	}
	q->k = 0;
	q->head = q->tail = NULL;
}

2.3.test.c

#define _CRT_SECURE_NO_WARNINGS
#include"queue.h"

int main()
{
	Queue q;
	QueueInit(&q);

	QueuePush(&q, 0);
	QueuePush(&q, 1);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	QueuePush(&q, 6);

	printf("%d\n", QueueSize(&q));

	printf("%d ", QueueFront(&q));

	printf("%d\n", QueueBack(&q));

	printf("%d ", QueueFront(&q));
	QueuePop(&q);

	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	
	printf("\n%d\n", QueueSize(&q));

	QueueDestory(&q);

	return 0;
}

运行结果如图,至于为什么是这些个结果,我们详细看以下鼠鼠的队列方案是如何实现的。

2.4.定义队列

typedef int QDatatype;

typedef struct QNode
{
	QDatatype _data;
	struct  QNode* _next;
}QNode;

typedef struct Queue
{
	int k;
	QNode* head;
	QNode* tail;
}Queue;

老样子我们将int重命名成QDatatype,方便以后代码的维护。

让后定义并重命名结构体QNode充当队列节点 ,这些节点根据数据元素的入队列或者出队列按需申请或者释放。QNode中成员_data用来存放数据元素,QNode中成员_next用来链接下一个节点。

又由于基于无头单向非循环链表(以下简称链表)实现的队列在入队列和出队列时分别需要链表尾插和头删,而且经常需要知道队列中数据元素的个数,我们定义并重命名结构体Queue来维护上面需求:Queue中成员k用来记录队列中数据元素个数;成员head用来指向链表头节点;成员tail用来指向链表尾节点。

大概这样子:

2.5.初始化队列

void QueueInit(Queue* q)
{
	assert(q);
	q->head = q->tail = NULL;
	q->k = 0;
}

断言防止传入的结构体变量地址为空(因为这个地址不可能为空)。将head和tail置成NULL,将k置成0即可。 

2.6.队尾入队列

void QueuePush(Queue* q, QDatatype data)
{
	assert(q);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	tmp->_data = data;
	tmp->_next = NULL;
	if (q->tail == NULL)
	{
		q->head = q->tail = tmp;
	}
	else
	{
		q->tail->_next = tmp;
		q->tail = tmp;
	}
	q->k++;
}

断言防止传入的结构体变量地址为空(这点以下不在赘述)。 队尾入队列其实就是链表尾插,先动态申请一个结构体QNode空间充当新节点,这个新节点的存放好想插入的数据元素,再让新节点链接好队列(链接队列是要区分队列是否为空),k加一即可。

2.7.对头出队列

void QueuePop(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	QNode* next = q->head->_next;
	free(q->head);
	q->head = next;
	if (q->head == NULL)
	{
		q->tail = NULL;
	}
	q->k--;
}

断言防止队列为空仍然出队列。常规来说再进行链表头删、k减一即可完成出队列,但要注意如果队列中只有一个数据元素(或者说链表只有一个节点)时,如果按常规操作的话会使得tail变成野指针,用上面一个if语句很好处理问题。 

2.8.获取队列队头元素

QDatatype QueueFront(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	return q->head->_data;
}

 断言防止队列为空仍然获取对头元素。返回head指向的节点成员_data即可。

2.9.获取队列队尾元素

QDatatype QueueBack(Queue* q)
{
	assert(q);
	assert(q->k > 0);
	return q->tail->_data;
}

  断言防止队列为空仍然获取对尾元素。返回tail指向的节点成员_data即可。

2.10.获取队列中有效元素的个数

int QueueSize(Queue* q)
{
	assert(q);
	return q->k;
}

根据设定可知,返回k即可。 

2.11.检测队列是否为空,如果为空返回非零结果,非空返回0

bool QueueEmpty(Queue* q)
{
	assert(q);
	return q->tail == NULL;
}

若tail指向NULL说明队列为空(或者说链表为空),则q->tail==NULL为真,返回真。若队列不为空逻辑跟队列为空逻辑相反,返回假。 

2.12.销毁队列 

void QueueDestory(Queue* q)
{
	assert(q);
	QNode* tmp = q->head;
	while (tmp)
	{
		QNode* next = tmp->_next;
		free(tmp);
		tmp = next;
	}
	q->k = 0;
	q->head = q->tail = NULL;
}

遍历链表将节点(这些节点都是动态申请的)都释放掉,再将head和tail置成NULL,并将k置成0即可。

 3.分析运行结果

佬们请看:

第一条语句:创建一个结构体Queue变量q;

第二条语句:初始化结构体变量q;

第三条到第十条语句:数据元素0、1、1、2、3、4、5、6依次入队列,执行完后队列想象图为: 

第十一条语句:执行printf函数,打印队列有效元素个数为8并换行。

第十二条和第十三条语句:均执行printf函数,分别打印对头元素0和队尾元素6,换行。

第十四条语句: 执行printf函数,打印对头元素0。

第十五条语句:对头元素0出队列,执行完第十五条语句后队列想象图为:

接下来while循环:当队列不为空时,打印对头元素再对头元素出队列。所以分别打印1、1、2、3、4、5、6。执行完while循环后,队列为空(或者说链表为空)。

再接下来打印队列有效元素个数为0,印证队列为空。再销毁队列。

4.ending

感谢阅读,有不对的地方欢迎像本鼠拿捏玩偶一样拿捏鼠鼠捏!

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Java初级数据结构与算法是指在Java编程语言中使用的基本数据结构和算法。在Java中,我们可以使用各种数据结构来存储和操作数据。常见的数据结构包括数组、链表、栈、队列和树等。这些数据结构可以用来解决各种实际问题,如搜索、排序、查找和插入等。 在Java中,我们可以使用ArrayList类来实现动态数组,LinkedList类来实现链表,Stack类来实现栈,Queue接口来实现队列,以及TreeSet和HashMap等类来实现树和哈希表等数据结构。这些数据结构提供了各种方法来操作和管理数据,如添加元素、删除元素、查找元素和遍历元素等。 此外,算法是解决问题的步骤和方法。在Java中,我们可以使用各种算法来处理数据结构中的数据。常见的算法包括线性搜索、二分搜索、冒泡排序、快速排序和图遍历等。这些算法可以帮助我们高效地处理和操作数据。 总结来说,Java初级数据结构与算法是指在Java编程语言中使用的基本数据结构和算法,包括数组、链表、栈、队列、树和哈希表等数据结构,以及搜索、排序、查找和遍历等算法。通过学习和掌握这些数据结构和算法,我们可以更好地解决实际问题并提高程序的效率。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [【Java】数据结构与算法入门](https://blog.csdn.net/LongLiveThePRC/article/details/124573277)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [1.0 JAVA数据结构与算法](https://blog.csdn.net/xiexieya233/article/details/124082025)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [java基础语法:数据结构和算法](https://blog.csdn.net/qq_50395011/article/details/109739043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X_chengonly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值