从0开始的(c语言)数据结构学习 4:队列

注:本文以造轮子为主,属于相对理论性、教学性的东西

理解:什么是队列?

你现在有一个放网球的竖球筒,你只能把球放到最上面,然后取出最下面的球,这就是队列。
队列
先进先出,后进后出

类似于栈,我们通常实现以下几个功能:(由于本质上和栈很类似,多余的解释我就不做了)

  1. 初始化队列
  2. 入队
  3. 出队
  4. 取队头

具体代码

注:本代码没有包含main函数(我在其中加入了一些很具体的注释来帮助理解,如果喜欢读代码的朋友可以直接看)
注2:如果你不想纯粹读代码,该代码所有的具体解释请下移

#include<iostream>
#include<fstream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char ElemType;
typedef int Status;


typedef struct QNode {
	ElemType data;
	struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
	QueuePtr front; //队头指针
	QueuePtr rear; //队尾指针
} LinkQueue;


Status InitQueue(LinkQueue &Q) //构造一个空队列Q
{
	Q.front = Q.rear = new QNode; //生成新结点作为头结点,队头和队尾指针指向此结点
	Q.front->next = NULL; //头结点的指针域置空
	return OK;
}

Status EnQueue(LinkQueue &Q, ElemType e) //入队:插入元素e为Q的新的队尾元素
{
	QueuePtr p;
	p = new QNode; //为入队元素分配结点空间,用指针p指向
	p->data = e; //将新结点数据域置为e
	p->next = NULL;
	Q.rear->next = p; //将新结点插入到队尾
	Q.rear = p; //修改队尾指针
	return OK;
}

Status DeQueue(LinkQueue &Q, ElemType &e) //出队:删除Q的队头元素,用e返回其值 
{
	QueuePtr p;
	if (Q.front == Q.rear)return ERROR; //若队列空,则返回ERROR
	p = Q.front->next; //p指向队头元素
	e = p->data; //e保存队头元素的值
	Q.front->next = p->next; //修改头指针
	if (Q.rear == p)
		Q.rear = Q.front; //最后一个元素被删,队尾指针指向头结点
	delete p; //释放原队头元素的空间
	return OK;
}

ElemType GetHead(LinkQueue Q) //取队头元素:返回Q的队头元素,不修改队头指针
{
	if (Q.front != Q.rear) //队列非空
		return Q.front->next->data; //返回队头元素的值,队头指针不变
}

对于代码的具体解释

1,前设_宏定义

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char ElemType;
typedef int Status;

没什么可说的。

2,前设_结构

typedef struct QNode {
	ElemType data;
	struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
	QueuePtr front; //队头指针
	QueuePtr rear; //队尾指针
} LinkQueue;

QNode:用于存储结点,每一个结点有着一个数据域(data)和一个指针域(next)。

LinkQueue:用于存储链队列的头和尾。

3,函数_初始化

Status InitQueue(LinkQueue &Q) {
	Q.front = Q.rear = new QNode;
	Q.front->next = NULL;
	return OK;
}

和栈不太相同的是,队列我们有着两个指针,头和尾。一般情况下,当我们的头尾指向同一个空结点的时候,代表着队列空了。

【作用解释】

对链队列进行初始化

思路:
  1. 创建一个新的结点,同时将头和尾都放到这里,此时新的结点为空(NULL)。
  2. 头结点的下一个结点同样为空。

4,函数_入队

Status EnQueue(LinkQueue &Q, ElemType e) {
	QueuePtr p;
	p = new QNode;
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return OK;
}
【作用解释】

在链队列的尾部加入一个新的数据e

思路:
  1. 为新的数据e创造空间(结点p),然后将它的下一个设为NULL(因为他在尾部,就是最后一个,他没有下一个)
	QueuePtr p;
	p = new QNode;
	p->data = e;
	p->next = NULL;
  1. 将原本尾的下一个改为当前的结点。(就是之前的最末尾现在尾部有了新的结点,所以它不再是尾部了)
    Q.rear->next = p;
  2. 将当前的结点改为尾部。
    Q.rear = p;

5,函数_出队

Status DeQueue(LinkQueue &Q, ElemType &e) 
{
	QueuePtr p;
	if (Q.front == Q.rear)return ERROR;
	p = Q.front->next;
	e = p->data;
	Q.front->next = p->next;
	if (Q.rear == p)
		Q.rear = Q.front;
	delete p;
	return OK;
}
【作用解释】

输出队列的头部,并删除

思路:
  1. 判断队列是不是空的(如果队列首尾相连,就是的。)
    if (Q.front == Q.rear)return ERROR;
  2. 用一个值保存原本的头结点(便于之后删除清理空间),然后把我们要的数据给e
	p = Q.front->next;
	e = p->data;
  1. 修正头结点,并判断修正后是不是头尾相连(是不是空的)
	Q.front->next = p->next;
	if (Q.rear == p)
		Q.rear = Q.front;
  1. 删除旧的结点
    delete p;

6,函数_取头结点

ElemType GetHead(LinkQueue Q)
{
	if (Q.front != Q.rear)
		return Q.front->next->data;
}

如果此时不是首尾相连(也就是不为空),则返回头结点下一个(也就是第一个结点)的数据域。

如果你是初学者:

试试写一个顺序队列,然后实现循环队列吧。没什么可写的了。

如果你想要没有注释的代码:

拿走,请。

#include<iostream>
#include<fstream>
using namespace std;

#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char ElemType;
typedef int Status;


typedef struct QNode {
	ElemType data;
	struct QNode *next;
} QNode, *QueuePtr;

typedef struct {
	QueuePtr front;
	QueuePtr rear;
} LinkQueue;


Status InitQueue(LinkQueue &Q)
{
	Q.front = Q.rear = new QNode;
	Q.front->next = NULL;
	return OK;
}

Status EnQueue(LinkQueue &Q, ElemType e)
{
	QueuePtr p;
	p = new QNode;
	p->data = e;
	p->next = NULL;
	Q.rear->next = p;
	Q.rear = p;
	return OK;
}

Status DeQueue(LinkQueue &Q, ElemType &e)
{
	QueuePtr p;
	if (Q.front == Q.rear)return ERROR;
	p = Q.front->next;
	e = p->data;
	Q.front->next = p->next;
	if (Q.rear == p)
		Q.rear = Q.front;
	delete p;
	return OK;
}

ElemType GetHead(LinkQueue Q)
{
	if (Q.front != Q.rear) 
		return Q.front->next->data; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值