队列是一种特殊的线性表,而线性表有顺序和链式存储两种,这里只讨论单向链式链表实现的队列模型,队列遵循的原则是先进先出,因此不管以链表的头部和尾部作为队列的头部,当弹出和压入元素的时候都会设计到队列中元素的移动。这里以链表头部为队列的尾部,以链表的尾部做为队列的头部,即压入元素时采用头插法,弹出元素时采用尾出法。
详细讲解参照https://www.bilibili.com/video/av27904891/?p=1
本次使用工具为vs2017,作者水平有限,若有问题请指出。
队列头文件:Queue_Link_Cplus.h
#pragma once
template<typename T>
struct QueueNode
{
QueueNode<T> *Next;
T item;
};
template<typename T>
class Queue_Link_Cplus
{
public:
//默认构造函数,创建一个队列
Queue_Link_Cplus();
//往队列里面压入元素
int Push_Item(T item);
//从队列头部弹出元素
T Pop_Item();
//获取队列头元素
T GetHeadItem();
//获取队列的元素个数
int GetItemNum();
//清空队列
int ClearQueue();
//释放分配的资源
~Queue_Link_Cplus();
private:
QueueNode<T> *QueueHead;
int QueueLen;
};
队列源文件:Queue_Link_Cplus.cpp
#include "pch.h"
#include "Queue_Link_Cplus.h"
#include "iostream"
using namespace std;
template<typename T>
Queue_Link_Cplus<T>::Queue_Link_Cplus()
{
this->QueueHead = new QueueNode<T>;
if (this->QueueHead == NULL)
{
cout << "创建队列失败 :Queue_Link_Cplus<T>::Queue_Link_Cplus()" << endl;
}
else
{
this->QueueHead->Next = NULL;
this->QueueLen = 0;
cout << "队列创建成功" << endl;
}
}
//释放手动开辟的节点
template<typename T>
Queue_Link_Cplus<T>::~Queue_Link_Cplus()
{
if(this->QueueHead != NULL)
{
QueueNode<T> *current = this->QueueHead->Next; //current指向0号节点处
QueueNode<T> *temp = NULL;
for (int i = 0; i < this->QueueLen - 1; i++) //循环完之后current指向最后一个元素
{
temp = current->Next;
if (current != NULL)
{
delete current;
}
current = temp;
}
delete this->QueueHead;
this->QueueHead = NULL;
}
this->QueueLen = 0;
}
//往队列里面压入元素
template<typename T>
int Queue_Link_Cplus<T>::Push_Item(T item)
{
int ret = 0;
if (this->QueueHead == NULL)
{
cout << "队列不存在" << endl;
ret = -1;
return ret;
}
else
{
//new节点
QueueNode<T> *queuedata = new QueueNode<T>;
queuedata->item = item; //复杂数据类型要重载=,防止浅拷贝
queuedata->Next = NULL;
if (this->QueueLen == 0) //队列为空
{
this->QueueHead->Next = queuedata;
this->QueueLen++;
}
else //队列非空,采用头插入压入节点,尾取法弹出节点
{
queuedata->Next = this->QueueHead->Next;
this->QueueHead->Next = queuedata;
this->QueueLen++;
}
return ret;
}
}
//从队列头部弹出元素
template<typename T>
T Queue_Link_Cplus<T>::Pop_Item()
{
T item;
if (this->QueueHead == NULL) //队列不存在
{
cout << "队列不存在,不能弹出元素" << endl;
memset(&item,0,sizeof(T));
return item;
}
else
{
if (this->QueueLen == 0) //队列为空
{
cout << "队列中元素个数为0,不能弹出元素" << endl;
memset(&item, 0, sizeof(T));
return item;
}
else
{
QueueNode<T> *current = this->QueueHead; //current指向头部
for (int i=0; i<this->QueueLen-1; i++) //循环完之后current指向最后一个元素的前一个元素
{
current = current->Next;
}
item = current->Next->item; //元素拷贝
if (current->Next != NULL)
{
delete current->Next;
}
current->Next = NULL;
this->QueueLen--;
return item;
}
}
}
//获取队列头元素
template<typename T>
T Queue_Link_Cplus<T>::GetHeadItem()
{
T item;
if (this->QueueHead == NULL) //队列不存在
{
cout << "队列不存在,get不到队头元素" << endl;
memset(&item, 0, sizeof(T));
return item;
}
else
{
if (this->QueueLen == 0) //队列为空
{
cout << "队列中元素个数为0,get不到队头元素" << endl;
memset(&item, 0, sizeof(T));
return item;
}
else
{
QueueNode<T> *current = this->QueueHead; //current指向头部
for (int i = 0; i < this->QueueLen - 1; i++) //循环完之后current指向最后一个元素的前一个元素
{
current = current->Next;
}
item = current->Next->item; //元素拷贝
return item;
}
}
}
//获取队列的元素个数
template<typename T>
int Queue_Link_Cplus<T>::GetItemNum()
{
int ret = 0;
if (this->QueueHead == NULL) //队列不存在
{
cout << "队列不存在" << endl;
ret = -1;
return ret;
}
else
{
return this->QueueLen;
}
}
//清空队列
template<typename T>
int Queue_Link_Cplus<T>::ClearQueue()
{
int ret = 0;
if (this->QueueHead == NULL) //队列不存在
{
cout << "队列不存在" << endl;
ret = -1;
return ret;
}
else
{
QueueNode<T> *current = this->QueueHead->Next; //current指向0号节点处
QueueNode<T> *temp = NULL;
for (int i = 0; i < this->QueueLen - 1; i++) //循环完之后current指向最后一个元素
{
temp = current->Next;
if (current != NULL)
{
delete current;
}
current = temp;
}
}
this->QueueLen = 0;
this->QueueHead->Next = NULL;
return ret;
}
测试队列源文件:_Queue_Link_Cplus_Test_.cpp
#include "pch.h"
#include "Queue_Link_Cplus.cpp"
#include "iostream"
#include "string"
using namespace std;
class person
{
public:
person()
{
}
person(string name,int age)
{
this->name = name;
this->age = age;
}
person(const person &obj)
{
this->name = obj.name;
this->age = obj.age;
}
person operator=(person obj)
{
this->name = obj.name;
this->age = obj.age;
return *this;
}
~person()
{
}
public:
string name;
int age;
};
//测试person类型数据
void test_person()
{
Queue_Link_Cplus<person> QLC;
person a[8] = { person("aaa",91),person("bbb",92),person("ccc",93),person("ddd",94),person("eee",95),person("fff",96),person("ggg",97),person("hhh",98) };
person data;
int ret = 0;
for (int i = 0; i < 7; i++) //插入7个元素
{
ret = QLC.Push_Item(a[i]);
if (ret != 0)
{
cout << "Push element into queue error : " << i << endl;
break;
}
}
//连续读取和弹出5个元素
printf("测试 压入,读取,弹出数据\n");
for (int i = 0; i < 5; i++) //操作5次
{
data = QLC.GetHeadItem();
cout << data.name << " " << data.age << endl;
data = QLC.Pop_Item();
cout << data.name << " " << data.age << endl;
}
//测试清空队列
printf("\n测试清空队列后, 压入,读取,弹出数据\n");
ret = QLC.ClearQueue();
if (ret == 0) //清空成功
{
for (int i = 0; i < 2; i++) //插入2个元素
{
ret = QLC.Push_Item(a[5 + i]);
if (ret != 0)
{
cout << "Push element into queue error : " << i << endl;
break;
}
}
for (int i = 0; i < 2; i++) //操作2次
{
data = QLC.GetHeadItem();
cout << data.name << " " << data.age << endl;
data = QLC.Pop_Item();
cout << data.name << " " << data.age << endl;
}
}
}
//测试int类型数据
void test_int()
{
Queue_Link_Cplus<int> QLC;
int a[] = { 1,2,3,4,5,6,7,8,9,10,11 };
int data = 0;
int ret = 0;
for (int i = 0; i < 7; i++) //插入7个元素
{
ret = QLC.Push_Item(a[i]);
if (ret != 0)
{
printf("Push element into queue error : %d \n", i);
break;
}
}
//连续读取和弹出5个元素
printf("测试 压入,读取,弹出数据\n");
for (int i = 0; i < 5; i++) //操作5次
{
data = QLC.GetHeadItem();
if (data != NULL)
{
printf("%d ", data);
}
data = QLC.Pop_Item();
if (data != NULL)
{
printf("%d ", data);
}
}
//测试清空队列
printf("\n测试清空队列后, 压入,读取,弹出数据\n");
ret = QLC.ClearQueue();
if (ret == 0) //清空成功
{
for (int i = 0; i < 2; i++) //插入2个元素
{
ret = QLC.Push_Item(a[8 + i]);
if (ret != 0)
{
printf("Push element into queue error : %d \n", i);
break;
}
}
for (int i = 0; i < 2; i++) //操作2次
{
data = QLC.GetHeadItem();
if (data != NULL)
{
printf("%d ", data);
}
data = QLC.Pop_Item();
if (data != NULL)
{
printf("%d ", data);
}
}
}
}
int main()
{
test_int();
test_person();
system("pause");
return 0;
}