数据结构之队列

数据结构之队列

队列和栈一样,也是一种思想,它是一种“先进先出”的思想,它本身可以是一个数组,也可以是一条链表!

同样,它仅仅只是一种思想,只要我们对数组或者链表,按照队列的规则操作即可。

下面举个排队打饭的例子让大家理解一下队列

排队打饭

ok,现在呢锤某人食堂开业了,来了五个人排队打饭,黑人先排,黄人再排,蓝人再排,绿人跟着,橙人慢了一点点排到了最后。

在这里插入图片描述

因为锤某人食堂,是个讲究先来先打原则的食堂

所以黑人就先打到饭溜溜球啦

在这里插入图片描述

按照这个规则

黄人打完,蓝人打,蓝人打完,绿人打,绿人打完,橙人打

在这里插入图片描述

就这样,终于全部人都打到饭啦!我们的白人大妈总算能休息休息了。

总结:

在锤某人的食堂,我们了解到,锤某人的食堂有个规则,那就是先排队的人先打饭。

那么在队列中呢,先进链表或数组的元素,先出队列

故队列是一种“先进先出”的思想,和栈恰好相反

我们还能发现我们的操作好像都是在窗口进行的!

所以可以知道,我们的操作基本上都是队尾进行操作!(尾插尾删)

那么接下来就是各位熟悉的代码环节咯,请各位动动小手,一块来!

代码

queue.h

这里使用的是我们熟悉的带头结点单链表哦!

注意队头结点(头结点)类型哦!

和前面我所写的单链表有所不同哈!

这样写单链表更加方便,并且省了一个结点的空间。

#ifndef __QUEUE_H__
#define __QUEUE_H__
#include<stdio.h>
#include<stdlib.h>

//带头结点的单链表
typedef int Elemtype;	//队列的元素类型

//创建队列的结点类型
typedef struct node
{
	Elemtype data;
	struct node* next;
}Node;

//创建队列队类型(头结点类型)
typedef struct queue
{
	Node* front;	//队头
	Node* rear;	//队尾
	int node_num;	//结点个数
}Queue; 

Queue* queue_init();	//初始化队(头结点)
Node* node_init(Elemtype d);	//初始化结点

int Node_enqueue(Queue* q, Node* n);	//结点入队
int Elemt_Enqueue(Queue* q, Elemtype d);	//元素入队

int Is_empty(Queue* q);	//判断队是否存在,队是否为空

Node* Node_Dequeue(Queue* q);	//结点出队
Elemtype Elemt_Dequeue(Queue* q);	//元素出队

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

void printf_queue(Queue* q);	//打印队列

#endif //!__QUEUE_H__

queue.c

准备工作!
#include"queue.h"//头文件不要忘记哦!

准备工作当然是初始化啦!

/*
* 初始化队列(头结点)
*/
Queue* queue_init()
{
	Queue* q = (Queue*)malloc(sizeof(Queue));
	q->front = NULL;
	q->rear = NULL;
	q->node_num = 0;
	return q;
}

/*
* 初始化结点
*/
Node* node_init(Elemtype d)
{
	Node* p = (Node*)malloc(sizeof(Node));
	p->next = NULL;
	p->data = d;
	return p;
}
判断队列是否为空,或者是否存在

有的时候需要用到,这里附上啦!

/*
* 判断一个队列是否为空,为空返回1,否则返回0
* 参数:Queue * 类型,传入队
* 返回值:int 类型,空队返回1,否则返回0
*/
int Is_empty(Queue* q)
{
	if (!q || !(q->rear))	//空队或队不存在
	{
		return 1;
	}
	return 0;
}
入队

入队分两种哈!

元素入队和结点入队

实际上没有太大区别,需要哪种用哪种叭!

/*
* 结点入队
* 参数:第一个参数:Queue * 类型,传入队
* 第二个参数:Node * 类型,传入结点
* 返回值:int 类型,入队成功返回1,入队失败返回0
*/
int Node_enqueue(Queue* q, Node* n)
{
	if (!q)	//队列不存在,返回0
	{
		printf("队列不存在,无法入队\n");
		return 0;
	}
	if (q->rear == NULL)//空队,从无到有
	{
		q->front = n;
		q->rear = n;
	}
	else//从少到多
	{
		q->rear->next = n;
		q->rear = n;
	}
	q->node_num++;
	return 1;	//队列存在,返回1
}
/*
* 元素入队
* 参数:第一个参数:Queue * 类型,传入队
* 第二个参数:Elemtype 类型,传入数据域
* 返回值:int 类型,入队成功返回1,入队失败返回0
*/
int Elemt_Enqueue(Queue* q, Elemtype d)
{
	if (!q)	//队列不存在,返回0
	{
		printf("队列不存在,无法入队\n");
		return 0;
	}
	Node* n = node_init(d);
	if (q->rear == NULL)//空队,从无到有
	{
		q->front = n;
		q->rear = n;
	}
	else
	{
		q->rear->next = n;
		q->rear = n;
	}
	q->node_num++;
	return 1;	//队列存在,返回1
}
出队

出队同样也是分两种哈

元素出队和结点出队!

需要啥咱们用啥。

/*
* 结点出队
* 参数:Queue * 类型,传入队
* 返回值:Node * 类型,出队成功,返回出队结点;出对失败,返回NULL
*/
Node* Node_Dequeue(Queue* q)
{
	if (Is_empty(q))//判断队列是否为空
	{
		printf("队列为空,出队失败!\n");
		return NULL;
	}
	Node* p = q->front;
	q->front = q->front->next;//令front指向下一个结点
	if (q->front == NULL)//判断队列(front)是否为空,为空令rear指向front
		q->rear = q->front;
	p->next = NULL;
	q->node_num--;
	return p;
}
/*
* 元素出队
* 参数:Queue * 类型,传入队
* 返回值:Elemtype 类型,出队成功,返回结点的数据域d;出对失败,返回NULL
*/
Elemtype Elemt_Dequeue(Queue* q)
{
	if (Is_empty(q))//判断队列是否为空
	{
		printf("队列为空,出队失败!\n");
		return NULL;
	}
	Elemtype d;	//存储p的数据域
	Node* p = q->front;
	d = p->data;
	q->front= q->front->next;//令front指向下一个结点
	if (q->front == NULL)//判断队列(front)是否为空,为空令rear指向front
		q->rear = q->front;
	p->next = NULL;//释放结点p
	free(p);
	q->node_num--;
	return d;
}
销毁队列

就是把整个队列全部都释放掉!

可不是直接free哦!

/*
* 销毁一个队列
* 参数:Queue * 类型,传入队
* 返回值:void
*/
void Destory_queue(Queue* q)
{
	if (q==NULL)//判断队列是否存在
	{
		printf("队列不存在,无需销毁!\n");
		return;
	}
	//先删除结点
	Node* traversal = q->front;//遍历指针
	while(traversal)//一个节点一个节点销毁释放内存
	{
		q->front = q->front->next;
		traversal->next = NULL;
		free(traversal);
		traversal = q->front;
		q->node_num--;
	}
	//再删除头
	q->rear = NULL;//令rear指向NULL,返回初始化状态
	free(q);
}

打印队列

想看队列有啥嘛?

想知道你就得用我!

/*
* 打印队列
* 参数:Queue * 类型,传入队
* 返回值:void
*/
void printf_queue(Queue* q)
{
	if (!q)//判断队列是否存在
	{
		printf("队列不存在,打印失败!\n");
		return;
	}
	if (q->front==NULL)//判断队列是否为空
	{
		printf("队列为空,打印失败!\n");
		return;
	}
	Node* p = q->front;
	while (p)//开始打印
	{
		printf("%d ", p->data);
		p = p->next;
	}
	putchar('\n');
}

好啦,看到这里的大佬们就会发现我好像没有创建队列欸。

实际上呢,队列是需要一个一个入队的。

所以我们,只需要初始化一个队头,然后再不断进行入队操作就能获得一个队列啦!

注意:由于编译器原因可能scanf为scanf_s将_s删去即可!

感谢各位的观看啦,希望对各位有所帮助,有问题一定要提出来哦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值