队列的实现

目录

一. 队列的概念和结构

二. 队列的实现方式

1. 顺序表

2. 链表

三. 队列各个功能的实现

1. 结构体的定义

2.  队列的初始化

3. 队列的插入操作(此处为尾插)

4. 返回队头和队尾的值

5. 队列的删除操作(此处为头删)

6. 判断队列是否为空

 7. 返回队列的元素个数

8. 销毁队列

四. 完整代码

1. queue.h

2. queue.c

 3. test.c


一. 队列的概念和结构

队列是只允许在一端插入操作,在另一端进行删除数据操作的特殊线性表,具有先进先出的特点

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

出队列:进行删除操作的一端称为队头

 

二. 队列的实现方式

1. 顺序表

队列几乎不考虑用数组实现,因为其先进先出的特性导致数组进行插入删除操作很麻烦

下标为0处当队尾时,每次插入就要移动原队列的所有元素。

下标为0处做队头时,每次删除都要移动原队列的所有元素-1。

 并且容易浪费内存等等

2. 链表

省空间的话优先考虑用单链表实现(带尾指针,方便头插尾删或者尾插头删)

1. 头做队头,尾做队尾时:尾插入队,头删出队

2. 头做队尾,尾做队头时:头插入队,尾删出队

三. 队列各个功能的实现

1. 结构体的定义
typedef int QueueType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QueueType val;

}QNode,*pQNode;

typedef struct Queue
{
	pQNode head;
	pQNode tail;
	int size;
}Queue;

我们需要一个头指针和一个尾指针,如果将其整合为一个结构体会方便的多,并且免去了使用二级指针来改变头指针和尾指针,记录元素个数也方便许多

2.  队列的初始化
void QueueInit(Queue* pq)
{
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}
3. 队列的插入操作(此处为尾插)
void QueuePush(Queue* pq, QueueType x)
{
	pQNode tmp = (pQNode)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc:fail\n");
		return;
	}
	tmp->next = NULL;
	tmp->val = x;
	if (pq->tail == NULL)
	{

		pq->head = tmp;
		pq->tail = tmp;
	}
	else
	{
		pq->tail->next = tmp;
		pq->tail = tmp;
	}
	pq->size++;
}

插入第一个值需要额外判断将头指针赋值,其余就不必管头指针

4. 返回队头和队尾的值
QueueType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->val;
}

QueueType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail);

	return pq->tail->val;
}

一定要判断头指针和尾指针指向是否为空,否则可能会使用野指针

5. 队列的删除操作(此处为头删)
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);//要是没有节点就报错
	pQNode tmp = pq->head;
	if (pq->head == pq->tail)//如果只有一个节点
		pq->tail = NULL;
	pq->head = pq->head->next;
	free(tmp);
	tmp = NULL;
	pq->size--;
}

只有一个节点时要使尾指针置空否则再次插入时尾指针指向不为空导致使用野指针

6. 判断队列是否为空
bool QueueEmpty(Queue* pq)
{
    return pq->head==NULL && pq->tail == NULL;
}
 7. 返回队列的元素个数
int QueueSize(Queue* pq)
{
	return pq->size;
}
8. 销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	while (pq->head)
	{
		pQNode tmp = pq->head;
		pq->head = pq->head->next;
		free(tmp);
		tmp = NULL;
	}
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

四. 完整代码

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

typedef int QueueType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QueueType val;

}QNode,*pQNode;

typedef struct Queue
{
	pQNode head;
	pQNode tail;
	int size;
}Queue;

void QueueInit(Queue* pq);

//头删  尾插
void QueuePush(Queue* pq, QueueType x);

QueueType QueueFront(Queue* pq);

QueueType QueueBack(Queue* pq);

void QueuePop(Queue* pq);

bool QueueEmpty(Queue* pq);

void QueueDestroy(Queue* pq);

int QueueSize(Queue* pq);
2. queue.c
#include"queue.h"

void QueueInit(Queue* pq)
{
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

void QueuePush(Queue* pq, QueueType x)
{
	pQNode tmp = (pQNode)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc:fail\n");
		return;
	}
	tmp->next = NULL;
	tmp->val = x;
	if (pq->tail == NULL)
	{

		pq->head = tmp;
		pq->tail = tmp;
	}
	else
	{
		pq->tail->next = tmp;
		pq->tail = tmp;
	}
	pq->size++;
}

QueueType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);

	return pq->head->val;
}

QueueType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail);

	return pq->tail->val;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);//要是没有节点就报错
	pQNode tmp = pq->head;
	if (pq->head == pq->tail)//如果只有一个节点
		pq->tail = NULL;
	pq->head = pq->head->next;
	free(tmp);
	tmp = NULL;
	pq->size--;
}

bool QueueEmpty(Queue* pq)
{
	return pq->head==NULL && pq->tail == NULL;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	while (pq->head)
	{
		pQNode tmp = pq->head;
		pq->head = pq->head->next;
		free(tmp);
		tmp = NULL;
	}
	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

int QueueSize(Queue* pq)
{
	return pq->size;
}
 3. test.c
#include"queue.h"

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

	QueuePush(&pq, 1);
	QueuePush(&pq, 2);
	QueuePush(&pq, 3);
	QueuePush(&pq, 4);
	while (!QueueEmpty(&pq))
	{
		printf("%d  ", QueueFront(&pq));
		QueuePop(&pq);
	}
	//printf("%d\n", QueueSize(&pq));
	//printf("%d\n", QueueFront(&pq));
	//printf("%d\n", QueueBack(&pq));
	//QueuePop(&pq);
	//printf("%d\n", QueueSize(&pq));
	//printf("%d\n", QueueFront(&pq));
	//printf("%d\n", QueueBack(&pq));
	QueueDestroy(&pq);

	QueuePush(&pq, 1);
	QueuePush(&pq, 2);
	QueuePush(&pq, 3);
	QueuePush(&pq, 4);
	while (!QueueEmpty(&pq))
	{
		printf("%d  ", QueueFront(&pq));
		QueuePop(&pq);
	}
	QueueDestroy(&pq);
}

这篇文章就到这里啦~(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤

感谢各位支持

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值