队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的尾端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先 进先出(FIFO—first in first out)线性表。
优点:链表实现的队列,需要包含头结点和尾结点,从头部删除节点时或尾部添加节点只需要记住头结点的地址或者是尾部结点的地址即可,可以很快申请内存地址。空间扩展容易,因为不需要连续申请内存,数据可以存储在任意的内存地址中
缺点:查询数据的时候效率低下,无法像循环列表一样随机读写,因为链表中的数据都是通过头节点向后遍历找到的,要找链表中的一个数据,必须就是从头开始找起(双链表可以从尾节点向前遍历)
我流链式队列:创建两个结构体,链队列结构体用于管理首尾指针;节点结构体负责组成队列元素。计划用一个指针变量维护链队列的实例化对象
内存管理结构:
- 一个ptr ->链队列实例化对象
- ptr->front->节点组的首节点
- ptr->rear->节点组的尾节点
注意只有链队列指针在栈区创建,其余的指针变量和数据变量都在堆区创建
#include <iostream>
using namespace std;
struct Node;
struct LinkQueue{//封装一个链队列结构体
Node* front;
Node* rear;
};
struct Node {//封装一个节点结构体
Node* next;//元素指针域
int data;//元素数据域
};
bool empty(LinkQueue*tmp) {
return tmp->front == NULL;//头指针指向空时可认为是空列表
}
Clear()——清空链队函数
- 创建临时指针p
- 进循环,p指向头指针指向的节点,头指针向下一个节点移动后,指针p删除上一个节点
- 最终链队里无节点,头指针会指向NULL,此时也要将尾指针指向NULL
传入的参数为一个指向链队列对象的指针,无返回值
void Clear(LinkQueue*tmp) {//清空链队列函数
Node* p;
while (tmp->front != NULL) {//迭代法删除节点
p = tmp->front;
tmp->front = tmp->front->next;
delete p;
}
tmp->rear = NULL;//尾指针置空
cout << "队列已清空" << endl;
}
Size()——长度查询函数
- 定义临时指针p
- 指针p指向第一个节点
- 定义整形变量count(用于计数)
- 进入循环,遍历链表,count计数循环执行次数
传入的参数为一个指向链队列对象的指针,返回一个整形值
int Size(LinkQueue*tmp) {//查询链队列长度
Node* p = tmp->front;
int count = 0;//计数变量初始化为0
while (p) {
count++;//计数值增加
p = p->next;//临时指针向下一个节点位移
}
cout << "队列长度为 " << count << endl;
return count;
}
EnQueue()——元素入列函数
- 判断队列是否为空,(1)不为空则令头尾指针指向一个新节点,(2)并对节点赋值
- 若不为空,(1)则尾节点的指针指向一个新开辟的节点,(2)对新节点赋值,(3)尾指针移动到下一个节点
传入一个指向链队列对象的指针,和一个整形变量,无返回值
void EnQueue(LinkQueue*tmp,int x) {//入列函数
if (tmp->rear == NULL) {//当rear指针置空时(队列没元素时)
tmp->front = tmp->rear = new Node();//front和rear指向新节点
tmp->front->data = x;
cout << x << " 入列" << endl;
}
else {//此时队列有元素
tmp->rear->next = new Node();//尾指针指向节点的next指针指向新节点
tmp->rear->next->data = x;
tmp->rear = tmp->rear->next;
cout << x << " 入列" << endl;
}
}
DeQueue()——元素出列函数
- 首先检查队列是否为空,是则直接返回
- 不为空,则定义一个临时指针p,指向第一个节点
- 将第一个节点的值存储在一个临时变量中
- 头指针移动到下一节点
- 判断头指针是否为空,为空则将尾指针也置空
- 删除p指向的节点
传入一个指向链队列的指针,返回一个整形值
int DeQueue(LinkQueue*tmp) {//出列函数
if (empty(tmp)) {
cout << "队列为空,无元素可出列" << endl;
return 0;
}
Node* p = tmp->front;
int value = tmp->front->data;
tmp->front = tmp->front->next;
if (tmp->front == NULL)//当唯一元素出列后,队列无元素,首节点和尾节点都置空
tmp->rear == NULL;
delete p;
cout << value << " 出列" << endl;
return value;
}
getHead()——队首元素获取函数
- 首先用empty函数检查队列是否为空,是空则直接返回
- 不为空则输出首元素值
传入一个指向链队列的指针,返回一个整形值
int getHead(LinkQueue* tmp) {//得到队首元素值
if (empty(tmp)) {
cout << "队列为空,无元素可出列" << endl;
return 0;
}
cout << "队首元素值为 " << tmp->front->data<<endl;
return tmp->front->data;
}
CreateLinkQueue()——链队列创建函数
- 定义临时指针tmp指向一个链队列对象
- 头指针和尾指针置空
无传入参数,返回一个指向指向链队列对象的指针
LinkQueue* CreateLinkQueue() {
LinkQueue* tmp = new LinkQueue();//分配空间
tmp->front == NULL;//头指针置空
tmp->rear == NULL;//尾指针置空
cout << "已创建新队列" << endl;
return tmp;
}