【数据结构】-链队列(无头结点)

1.头文件及类型定义

#include<stdio.h>
#include<stdlib.h>
#define ElemType int

2.链队列类型定义

typedef struct LinkNode {		//链式队列的结点类型定义
	ElemType data;				//每个结点存放一个数据元素
	struct LinkNode* next;		//指向下一个结点的指针
}LinkNode;

typedef struct {				//链式队列定义
	LinkNode* front, * rear;	//队列的队头指针和队尾指针 
}LinkQueue;

3.函数声明

/*函数声明*/
void InitQueue(LinkQueue& Q);				//1.初始化队列
bool LiQueueEmpty(LinkQueue Q);				//2.判空
bool EnQueue(LinkQueue& Q, ElemType x);		//3.入队操作
bool ExQueue(LinkQueue& Q, ElemType& x);	//4.出队操作
bool GetHead(LinkQueue Q, ElemType& x);		//5.获取队头元素

4.基本操作

4.1 初始化队列

//1.初始化队列(无头结点)
void InitQueue(LinkQueue& Q) {
	Q.front = Q.rear = NULL;		//初始化时front、rear都指向NULL
}

4.2 判空

//2.判空(无头结点)
bool LiQueueEmpty(LinkQueue Q) {
	return (Q.front == NULL);
	//或者return (Q.rear == NULL);
}

4.3 入队

//3.入队操作(无头结点)
bool EnQueue(LinkQueue& Q, ElemType x) {
	LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));
	if (s == NULL)
		return false;	//内存不足,分配失败
	s->data = x;		//为新结点赋值
	s->next = NULL;		//因为新结点只能从队尾插入,即新结点为最后一个结点,其next指针为NULL
	if (Q.rear == NULL)		//如果当前队列为空,入队结点为第一个结点
		Q.front = Q.rear = s;	//修改队头和队尾指针
	else {				//其他结点的插入与带头结点的插入一致
		Q.rear->next = s;		//新结点插入到rear之后:原先队尾指针所指结点的next指向新结点
		Q.rear = s;			//修改队尾结点指针,指向新的队尾结点
	}
	return true;
}

4.4 出队

//4.出队操作(无头结点)
bool ExQueue(LinkQueue& Q, ElemType& x) {
	if (Q.front == NULL)
		return false;	//队空,报错
	LinkNode* p = Q.front;	//找到队头元素
	x = p->data;				//变量x返回队头元素
	//下面这行不可改为p = p->nxet,p只是用来过渡的,真正要改变的是Q.front
	Q.front = p->next;	//修改队头指针:将队头结点的后继结点赋给队头指针
	if (Q.rear == p)			//如果此次为最后一个结点出队	
		Q.rear = Q.front = NULL;		//修改rear指针,队列置空
	free(p);		//释放结点空间
	return true;
}

4.5 获取队头元素

//5.获取队头元素
bool GetHead(LinkQueue Q, ElemType& x) {
	if (Q.front == NULL)		//队空,报错
		return false;
	LinkNode* p = Q.front;	//找到队头元素
	x = p->data;		//x返回队头元素
	return true;
}

4.6 main函数


int main() {
	LinkQueue Q;		//声明一个链式队列(不分配内存空间)

	/*1、初始化队列*/
	InitQueue(Q);

	/*2、判空*/
	if (LiQueueEmpty(Q))
		printf("当前队列为空!\n");
	else
		printf("当前队列非空!\n");

	/*3、入队操作*/
	ElemType e1;
	printf("请输入入队元素的值:");
	scanf("%d", &e1);
	if (EnQueue(Q, e1))
		printf("新元素入队成功!\n");
	else
		printf("队列已满,新元素入队失败!\n");

	/*4、读取队头元素*/
	ElemType e2 = -1;
	if (GetHead(Q, e2))
		printf("读取队头元素成功,当前队头元素值为:%d\n", e2);
	else
		printf("队列已空,读取队头元素失败!\n");

	/*5、出队操作*/
	ElemType e3 = -1;
	if (ExQueue(Q, e3))
		printf("队头元素出队成功,出队元素值为:%d\n", e3);
	else
		printf("队列已空,队头元素出队失败!\n");

	/*6、读取队头元素*/
	ElemType e4 = -1;
	if (GetHead(Q, e4))
		printf("读取队头元素成功,当前队头元素值为:%d\n", e4);
	else
		printf("队列已空,读取队头元素失败!\n");

	return 0;
}

5.小结

  1. 关于链队列
    队列的链式存储称为链队列,它实际上就是一个同时带有队头指针队尾指针单链表,同单链表一样,队列也有两个版本,带头结点和不带头结点,本文先讨论不带头结点的情况。
  2. 关于定义
    从类型定义来看,不难看出,先定义了一个链结点的类型,包括数据域和指向下一个结点的指针域,这个与单链表完全相同,又定义了一个链队列类型,旨在声明这是一个队列,包含头指针和尾指针。
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页