循环队列:链表实现
结构描述
typedef int DataType;
typedef struct QueueNode {
DataType A;
struct QueueNode * Next;
}Node;
class QueueCycLinked {
public:
//队头、队尾指针
Node * Front;
Node * Next;
//队列操作
//把元素X入队
void Push(DataType X);
//把队头元素出队
void Pop();
//销毁队列
void MakeEmpty();
//判断队列是否为空,为空返回true
bool IsEmpty();
//初始化(创建空队)
void Init();
//获取队头,队尾元素
DataType GetFront();
DataType GetRear();
//创建节点
Node * BuyNode(DataType X);
};
初始化:(创建空队)
把 Front
和 Rear
指向空。
void QueueLinked::Init() {
Front = Rear = nullptr;
}
判空
当 Front
指向空时,即队列为空
bool QueueLinked::IsEmpty() {
return Front == nullptr;
}
创建节点
把数据 X
传到 BuyNode()
方法中,用 malloc()
函数动态分配一个节点:
- 分配成功:返回节点指针;
- 分配失败:报错退出;
Node * QueueLinked::BuyNode(DataType X) {
Node * NewNode = (Node *)malloc(sizeof(Node));
// Node * NewNode = (Node *)malloc(sizeof(DataType));
if (NewNode == nullptr) {
cout << "Malloc Failed!" << endl;
exit(-1);
}
else {
NewNode->A = X;
NewNode->Next = nullptr;
}
return NewNode;
}
入队
- 当队列为空时:创建新节点把
Front
与Rear
都指向新节点,并构造出一个循环链表。 - 当队列非空时:
- 创建新节点
NewNode
,并令其指针域指向Front
; - 让
Rear->Next
指向NewNode
, - 再将
Rear
向后移动一位,即指向NewNode
。
- 创建新节点
void QueueCycLinked::Push(DataType X) {
if (IsEmpty()) {
Front = Rear = BuyNode(X);
//构造出一个循环链表。
Rear->Next = Front;
}
else {
//生成新节点
Node * NewNode = BuyNode(X);
//NewNode->Next指向Front
NewNode->Next = Front;
//Rear->Next 指向NewNode
Rear->Next = NewNode;
//重新设置Rear指针的指向
Rear = Rear->Next;
}
}
出队
- 当队列为空时:报错
- 当队列非空时:
- 只有一个元素时:直接释放
- 多个元素时:
Front
向后移动一位,并用Tmp
变量保存之前的Front
;- 重新设置
Rear->Next
的指向,即指向当前的Front
,即Rear->Next = Front
,或者Rear->Next = Tmp->Next
; - 释放
Tmp
并将其置空,防止悬空指针。
void QueueCycLinked::Pop() {
if (IsEmpty()) {
cout << "Queue Is Empty !" << endl;
exit(-1);
}
else if (Front == Rear) {
free(Front);
Init();
}
else {
//向后移动一位
Node * Tmp = Front;
Front = Front->Next;
//保持循环链表结构
Rear->Next = Front;
//删除原来的Front指针指向的节点
free(Tmp);
Tmp = nullptr;
}
}
摧毁循环队列
用 while
循环,以 IsEmpty()
的值为条件,一直出队,直至队列为空,即 IsEmpty()
为真时队列出队完毕
void QueueCycLinked::MakeEmpty() {
while (!IsEmpty()) {
cout << Front->A << " ";
Pop();
// 释放过的节点无法打印,导致段错误
// cout << Front->A << " Has Been Poped!" << endl;
cout << "Has Been Poped!" << endl;
}
cout << "Queue Has Been Completed!" << endl;
}
获取头尾元素
直接返回指针指向的数据域即可,若表为空,则不可获取
DataType QueueCycLinked::GetFront() {
if (IsEmpty()) {
cout << "Queue Is Empty!" << endl;
exit(-1);
}
return Front->A;
}
DataType QueueCycLinked::GetRear() {
if (IsEmpty()) {
cout << "Queue Is Empty!" << endl;
exit(-1);
}
return Rear->A;
}
踩坑记录
在写摧毁队列的时候,想打印元素出队信息出来结果写错了
应该把元素信息在出队前打印,因为出队后打印的就是下一个元素了
void QueueCycLinked::MakeEmpty() {
while (!IsEmpty()) {
cout << Front->A << " ";
Pop();
// 释放过的节点无法打印,导致段错误
// cout << Front->A << " Has Been Poped!" << endl;
cout << "Has Been Poped!" << endl;
}
cout << "Queue Has Been Completed!" << endl;
}
标签:Node,队列,Next,链表,DataType,Front,NewNode,数据结构,Rear
From: https://www.cnblogs.com/codels/p/18309467