队列的专题讲解

一,队列的概念及结构

概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表

队列具有先进先出 FIFO(First In First Out)

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

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

入栈顺序 1

出栈顺序 N

入队列顺序 1

出队列顺序 1

结构 

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}QNode;

 

二,队列的应用

1,抽号

2,广度优先遍历 

如共同好友推荐

三,队列的实现

思考:

进行队列的添加删除

void QueuePush(QNode** pphead, QNode** pptail, QDataType x);
void QueuePop(QNode** pphead, QNode** pptail);

使用二级指针固然可行,但略微繁琐

考虑使用结构体,包含头尾指针 

2,

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

思考:为什么单链表实现时不使用?因为队列只需要进行尾插不需要进行尾删,而单链表的尾删需要的是尾结点的前一个节点 

1,Queue的初始化

void QueueInit(Queue* pq);

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

2,队列的尾插

void QueuePush(Queue* pq, QDataType x);

void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->next = NULL;
	newnode->val = x;

	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

3,队列的头删

void QueuePop(Queue* pq);

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	/*QNode* next = pq->phead->next;
	free(pq->phead);
	pq->phead = next;

	if (pq->phead == NULL)
		pq->ptail = NULL;*/

	// 一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else // 多个节点
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}

	pq->size--;
}

若只有一个节点,则会导致ptail为空指针 

 

QNode* next = pq->phead->next;
	free(pq->phead);
	pq->phead = next;

	if (pq->phead == NULL)
		pq->ptail = NULL;
// 一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else // 多个节点
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}

	pq->size--;

free为释放指向的节点,不是指针 

 4,获取队列的头数据

QDataType QueueFront(Queue* pq);

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->val;
}

5,获取队列的尾数据

QDataType QueueBack(Queue* pq); 

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}

6,获取队列的个数 

int QueueSize(Queue* pq);

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

7,队列的判空

bool QueueEmpty(Queue* pq);

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

8,队列的销毁

void QueueDestroy(Queue* pq);

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);

		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

四,总代码预览

Queue.h

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


typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}QNode;

typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;

void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);

// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);

// 取队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);

int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);

 队尾插入
//void QueuePush(QNode** pphead, QNode** pptail, QDataType x);
 队头删除
//void QueuePop(QNode** pphead, QNode** pptail);

Queue.c

#include"Queue.h"

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);

	QNode* cur = pq->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);

		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

// 队尾插入
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}

	newnode->next = NULL;
	newnode->val = x;

	if (pq->ptail == NULL)
	{
		pq->phead = pq->ptail = newnode;
	}
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}

	pq->size++;
}

// 队头删除
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->size != 0);

	/*QNode* next = pq->phead->next;
	free(pq->phead);
	pq->phead = next;

	if (pq->phead == NULL)
		pq->ptail = NULL;*/

	// 一个节点
	if (pq->phead->next == NULL)
	{
		free(pq->phead);
		pq->phead = pq->ptail = NULL;
	}
	else // 多个节点
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}

	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);

	return pq->phead->val;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}


int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->size == 0;
}

 

 

 

 

 

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
顺序队列是一种基于数组实现的队列,它的特点是先进先出,即先进入队列的元素先出队列。下面是一个简单的顺序队列的实现,使用C++语言: ```cpp const int MAXSIZE = 100; // 队列最大容量 class SeqQueue { private: int data[MAXSIZE]; // 存储队列元素的数组 int front; // 队头指针 int rear; // 队尾指针 public: SeqQueue() { front = rear = -1; // 初始化队头和队尾指针 } bool isEmpty() { return front == rear; // 队列为空的条件是队头指针和队尾指针相等 } bool isFull() { return rear == MAXSIZE - 1; // 队列已满的条件是队尾指针指向数组的最后一个元素 } bool enQueue(int x) { // 入队操作 if (isFull()) return false; // 如果队列已满,返回false rear++; // 队尾指针加1 data[rear] = x; // 将元素x存入队尾指向的位置 return true; } bool deQueue(int& x) { // 出队操作 if (isEmpty()) return false; // 如果队列为空,返回false front++; // 队头指针加1 x = data[front]; // 取出队头元素 return true; } }; ``` 在这个实现中,我们将队列元素存储在一个数组中,使用front和rear分别指向队列的头部和尾部。isEmpty和isFull方法用于判断队列是否为空或已满。enQueue方法用于将元素加入队列尾部,deQueue方法用于从队列头部取出元素。 需要注意的是,这个实现中没有考虑队列的扩容问题,如果队列已满,入队操作将会失败。在实际应用中,需要根据具体情况来进行扩容操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值