代码区
#include<iostream>
#include<string>
using namespace std;
//设置节点类
class Node
{
public:
int data;
Node* next;
};
//设置链式队列类
class LinkQueue
{
public:
LinkQueue(); //初始化链表队列
~LinkQueue(); //释放队列的储存空间
void EnQueue(int e); //入队
int DeQueue(); //出队
int GetHead(); //获取队列队头元素
int Empty(); //判断队列是否为空
int GetLength(); //获取队列长度
private:
Node* front, * rear; //队头、队尾指针,只有设置为节点类型,才可以指向节点
int Length; //随时记录队列长度
};
//队列初始化
LinkQueue::LinkQueue()
{
//设置空的头节点
Node* s = nullptr;
s = new Node;
s->next = nullptr;
//令队头队尾指针指向头节点s
front = rear = s;
Length = 0;
}
//队列销毁
LinkQueue::~LinkQueue()
{
//设置一个临时的节点q(注意,并没有给他开辟堆区内存),储存front的下一个节点
//以此,递推下去,直到最后
Node* q;
while (front)
{
q = front->next;
delete front;
front = q;
}
}
//入队
void LinkQueue::EnQueue(int e)
{
//建立一个需要置于队列中的节点
Node* s = nullptr;
s = new Node;
s->data = e;
s->next = nullptr;
//将节点s插入到队尾(需注意)
rear->next = s;
rear = s;
//队列长度加一
Length++;
cout << "入队成功" << endl
<< "---------------" << endl;
}
//出队
int LinkQueue::DeQueue()
{
//x用来储存出队的数据
//设置一个节点用来截取需要出队的节点
int x;
Node* p = nullptr;
if (rear == front)
{
cout << "队列为空" << endl
<< "---------------" << endl;
}
p = front->next;
x = p->data;
front->next = p->next;
if (rear == p)
{
front = rear;
}
else
{
//当出队节点为最后一个时,要交给析构函数来释放,
//如果没有这个else,则会可能会出现内存二次释放的问题
delete p;
}
//delete p;
Length--;
return x;
}
//获得队头
int LinkQueue::GetHead()
{
return front->next->data;
}
//判断是否为空
int LinkQueue::Empty()
{
if (front == rear) return 1;
else return 0;
}
//获得队列长度
int LinkQueue::GetLength()
{
return Length;
}
void test02()
{
LinkQueue q;
int a;
int i = 0;
//入队
for (i = 0; i < 3; i++)
{
cout << "开始入队:" << endl;
cin >> a;
q.EnQueue(a);
}
//获取队列长度
cout << "入队后,队列长度为:" << q.GetLength() << endl
<< "---------------" << endl;
//出队
for (int j = 0; j < 3; j++)
{
cout << "开始出队:" << endl;
cout << "第" << i - q.GetLength() << "位,出队内容为:" << q.DeQueue() << endl
<< "---------------" << endl;
}
//获取队列长度
cout << "出队后,队列长度为:" << q.GetLength() << endl
<< "---------------" << endl;
}
int main()
{
test02();
system("pause");
return 0;
}
写完代码之后的一些观点:
该代码的难点就在于,对节点释放的处理,本代码中通过对象默认调用析构函数的方法,将队列的销毁融入,而不是单独在列出,也因此,在出列函数的释放中,可能会存在重复释放的冲突,
一些解决这个冲突的想法,用宏将那个“截取出队的临时节点”定义为全局变量,如此,其释放,便不会限制在局部的函数中,变得灵活多变,让“出队函数”不会再包含释放内存相关的内容,将这个全局变量的释放放到“队列销毁函数”中,如此,再通过if的条件判断,进行讨论,这样,或许会更为直观的看到哪里需要避免重复释放。