【数据结构】链队列

1.链队列

链式队列----用链表实现,链式队列就是一个操作受限的单向链表
在这里插入图片描述
之前单链表结构体设计的时候,当时发现头节点所需要的成员变量(next域),有效节点里都有,所以我们当时单链表头节点直接借用别人有效数据节点的结构体设计
所以我们之前常说头节点的数据域不使用,浪费掉。

现在设计链式队列,就会发现头节点需要两个指针域(front和rear)
这时再让头节点借用有效数据节点的结构体设计就不合适
所以我们需要将链式队列的头节点重新设计

这时有一个问题:重新设计的头节点需不需要数据域?
在这里插入图片描述
在这里插入图片描述

2.链式队列的头文件与函数声明

#pragma once

//链队列的头结点需要重新设计,而不是和单链表一样,一直使用人家有效元素的结构体设计
typedef int ELEM_TYPE;

//有效节点的结构体设计
typedef struct Node
{
	ELEM_TYPE data;
	struct Node *next;
}Node, *PNode;

//头结点的结构体设计:
typedef struct LQueue
{
	struct Node* front;//队头指针
	struct Node* rear;//队尾指针
}LQueue, *PLQueue;


//初始化
void Init_LQueue(struct LQueue* lq);

//入队
bool Push(struct LQueue* lq, ELEM_TYPE val);

//出队(还需要一个输出参数rtval,将出的值带出来)
bool Pop(PLQueue lq, ELEM_TYPE* rtval);

//获取队头元素值(还需要一个输出参数rtval,将出的值带出来)
bool Top(PLQueue lq, ELEM_TYPE* rtval);

//判空
bool IsEmpty(PLQueue lq);

//判满
bool IsFull(PLQueue lq);

//查找
struct Node* Search(PLQueue lq, ELEM_TYPE val);

//获取有效元素个数
int Get_length(PLQueue lq);

//清空
void Clear(PLQueue lq);

//销毁
void Destroy(PLQueue lq);

//打印
void Show(PLQueue lq);

3.函数

3.1初始化

将头节点两个指针置空

//初始化
void Init_LQueue(struct LQueue* lq)
{
	//assert
	lq->front = NULL;
	lq->rear = NULL;
}

3.2入队

入队,相当于单链表尾插,但是有队尾指针,方便操作
在这里插入图片描述
有一种特殊情况:插入之前是空的队列
在这里插入图片描述

//入队
bool Push(struct LQueue* lq, ELEM_TYPE val)
{
	//assert
	//链式结构 入队 不需要判满
	//1.购买新节点
	struct Node * pnewnode = (struct Node *)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);
	pnewnode->data = val;

	//2.找到合适插入位置(队尾插入)
	//3.插入

	//特殊情况:如果入队之前,是一个空的队列
	if(IsEmpty(lq))
	{
		lq->front = lq->rear = pnewnode;
		pnewnode->next = NULL;
	}
	else
	{
		pnewnode->next = lq->rear->next;
		lq->rear->next = pnewnode;

		lq->rear = pnewnode;//插入之后,将队尾指针更新一下
	}

	return true;
}

3.3出队

单链表头删,但是要注意头指针的值
只要队列不空,则先让rtval 将值带出来
在这里插入图片描述

特殊情况: 要判断一下 出的那个节点是否是仅剩下的唯一一个节点
在这里插入图片描述

//出队(还需要一个输出参数rtval,将出的值带出来)
bool Pop(PLQueue lq, ELEM_TYPE* rtval)
{
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}
	//只要队列不空,则先让rtval  将值带出来
	*rtval = lq->front->data; //这一步 不要忘

	//特殊情况: 要判断一下 出的那个节点是否是仅剩下的唯一一个节点
	if(lq->front->next == NULL)//仅有一个有效节点
	{
		struct Node *p = lq->front;//p == lq->rear; ok
		free(p);

		lq->front = lq->rear = NULL;
	}
	else
	{
		struct Node *p = lq->front;
		lq->front = p->next;

		free(p);
	}

	return true;
}

3.4获取队头元素值

//获取队头元素值(还需要一个输出参数rtval,将出的值带出来)
bool Top(PLQueue lq, ELEM_TYPE* rtval)
{
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}
	//只要队列不空,则先让rtval  将值带出来
	*rtval = lq->front->data; //这一步 不要忘

	return true;
}

3.5判空

bool IsEmpty(PLQueue lq)
{
	//assert
	return lq->front == NULL;
}

3.6查找

//查找
struct Node* Search(PLQueue lq, ELEM_TYPE val)
{ 
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}

	//不需要前驱的那个for 去遍历
	for(struct Node*p = lq->front; p!=NULL; p=p->next)
	{
		if(p->data == val)
		{
			return p;
		}
	}

	return NULL;
}

3.7获取有效元素个数

//获取有效元素个数
int Get_length(PLQueue lq)
{
	int count = 0;
	for(struct Node*p = lq->front; p!=NULL; p=p->next)
	{
		count++;
	}

	return count;
}

3.8销毁

//销毁
void Destroy(PLQueue lq)
{
	struct Node* p = lq->front;
	struct Node* q = NULL;
	while(p != NULL)
	{
		q = p->next;
		free(p);
		p = q;
	}

	lq->front = lq->rear = NULL;
}

4.链队列的源文件与函数实现

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "list_queue.h"


//初始化
void Init_LQueue(struct LQueue* lq)
{
	//assert
	lq->front = NULL;
	lq->rear = NULL;
}

//入队
bool Push(struct LQueue* lq, ELEM_TYPE val)
{
	//assert
	//链式结构 入队 不需要判满
	//1.购买新节点
	struct Node * pnewnode = (struct Node *)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);
	pnewnode->data = val;

	//2.找到合适插入位置(队尾插入)
	//3.插入

	//特殊情况:如果入队之前,是一个空的队列
	if(IsEmpty(lq))
	{
		lq->front = lq->rear = pnewnode;
		pnewnode->next = NULL;
	}
	else
	{
		pnewnode->next = lq->rear->next;
		lq->rear->next = pnewnode;

		lq->rear = pnewnode;//插入之后,将队尾指针更新一下
	}

	return true;
}

//出队(还需要一个输出参数rtval,将出的值带出来)
bool Pop(PLQueue lq, ELEM_TYPE* rtval)
{
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}
	//只要队列不空,则先让rtval  将值带出来
	*rtval = lq->front->data; //这一步 不要忘

	//特殊情况: 要判断一下 出的那个节点是否是仅剩下的唯一一个节点
	if(lq->front->next == NULL)//仅有一个有效节点
	{
		struct Node *p = lq->front;//p == lq->rear; ok
		free(p);

		lq->front = lq->rear = NULL;
	}
	else
	{
		struct Node *p = lq->front;
		lq->front = p->next;

		free(p);
	}

	return true;
}

//获取队头元素值(还需要一个输出参数rtval,将出的值带出来)
bool Top(PLQueue lq, ELEM_TYPE* rtval)
{
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}
	//只要队列不空,则先让rtval  将值带出来
	*rtval = lq->front->data; //这一步 不要忘

	return true;
}

//判空
bool IsEmpty(PLQueue lq)
{
	//assert
	return lq->front == NULL;
}

//判满 //链式结构不需要判满

//查找
struct Node* Search(PLQueue lq, ELEM_TYPE val)
{ 
	//assert
	if(IsEmpty(lq))
	{
		return false;
	}

	//不需要前驱的那个for 去遍历
	for(struct Node*p = lq->front; p!=NULL; p=p->next)
	{
		if(p->data == val)
		{
			return p;
		}
	}

	return NULL;
}

//获取有效元素个数
int Get_length(PLQueue lq)
{
	int count = 0;
	for(struct Node*p = lq->front; p!=NULL; p=p->next)
	{
		count++;
	}

	return count;
}

//清空
void Clear(PLQueue lq)
{
	Destroy(lq);
}

//销毁
void Destroy(PLQueue lq)
{
	struct Node* p = lq->front;
	struct Node* q = NULL;
	while(p != NULL)
	{
		q = p->next;
		free(p);
		p = q;
	}

	lq->front = lq->rear = NULL;
}

//打印
void Show(PLQueue lq)
{
	for(struct Node*p = lq->front; p!=NULL; p=p->next)
	{
		printf("%d ", p->data);
	}
	printf("\n");
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Shang_Jianyu_ss

感谢大哥

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

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

打赏作者

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

抵扣说明:

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

余额充值