数据结构与算法 (单)链队列
单链表实现队列
1.初始化队列
首先创建单链表,和队列结构,在队列结构中定义两个指针变量front、rear,分别用来指向队列的首部和为尾部。判断队列是否为空,是否已满。
#define MaxSize 5 //队列的最大容量
typedef int DataType; //队列中元素类型
typedef struct _QNode {
//(链表)结点结构
DataType data;
struct _QNode *next;
}QNode;//链表
typedef QNode * QueuePtr;
typedef struct Queue {
//队列结构
int length; //队列的长度
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;//队列
//队列初始化,将队列初始化为空队列
void InitQueue(LinkQueue *LQ) {
if(!LQ) return ; //判断是否为空
LQ->length = 0; //队列长度
LQ->front = LQ->rear = NULL; //把对头和队尾指针同时置 0
}
//判断队列为空
bool IsEmpty(LinkQueue *LQ) {
if(!LQ) return 0; //不为空
if (LQ->front == NULL)
{
return true;
}
return false;
}
//判断队列是否为满
bool IsFull(LinkQueue *LQ) {
if(!LQ) return false; //不为空
if (LQ->length == MaxSize) {
return true;
}
return false;
}
2.入队,向队列中插入元素
防御式判断队列各种不成立条件,无误后分配新节点,遵循队列规则,则(新节点)该节点为尾节点,所以next指针置为空。 若该当前队列为空队列,那么此节点就为首节点和尾节点,将首节点指针和尾节点指针同时指向该节点,否则队首指针不动,将队尾指针指向当前节点的next指针指向新节点,后将尾指针指向新节点。
//入队,将元素 data 插入到队列 LQ 中
bool EnterQueue(LinkQueue *LQ,DataType data){
if(!LQ) return false;
if(IsFull(LQ)){
cout<<"无法插入元素 "<<data<<", 队列已满!"<<endl;
return false;
}
QNode *qNode = new QNode;//分配新节点
qNode->data = data;
qNode->next = NULL; //将新节点的next指针置为空(先进先出原则)
if(IsEmpty(LQ)){
//空队列(新插入节点为首节点)
LQ->front = LQ->rear = qNode;//此插入节点为第一个节点也是最后一个节点
}else {
LQ->rear->next =qNode;//在队尾插入节点 qNode(队尾节点next指针指向新节点--实现插入)
LQ->rear = qNode; //队尾指向新插入的节点(队尾指针指向新节点为尾节点)
}
LQ->length++;//队列长度加1
return true;
}
3.出队,删除队首
定义一个临时变量保存首节点,以便释放内存。
//出队,将队列中队头的元素出队,其后的第一个元素成为新的队首
bool DeleteQueue(LinkQueue *LQ, DataType *data){
QNode * tmp = NULL;//临时变量,用来保存要被释放掉资源的队首
if (!LQ || IsEmpty(LQ)) {
cout << "队列为空!" << endl;
return false;
}
if (!data) return false;
tmp = LQ->front; //保存队首节点
LQ->front = tmp->next;//将队首指针指向原首节点的下一个节点
if (!LQ->front) LQ->rear = NULL;//如果队头出列后不存在其他元素,则 rear 节点也要置空
*data = tmp->data;
LQ->length--; //队列长度减1
delete tmp; //释放内存
return true;
}
其他功能在完整代码中,实现与顺序队列大体相同,只是实现方式不同而已。
完整代码
#include <stdio.h>
#include <Windows.h>
#include <iostream>
#include <iomanip>
using namespace std;
#define MaxSize 5 //队列的最大容量
typedef int DataType; //队列中元素类型
typedef struct _QNode {
//(链表)结点结构
DataType data;
struct _QNode *next;
}QNode;//链表
typedef QNode * QueuePtr;
typedef struct Queue {
//队列结构
int length; //队列的长度
QueuePtr front; //队头指针
QueuePtr rear; //队尾指针
}LinkQueue;//队列
//队列初始化,将队列初始化为空队列
void InitQueue(LinkQueue *LQ) {
if(!LQ) return ; //判断是否为空
LQ->length = 0; //队列长度
LQ->front = LQ->rear = NULL; //把对头和队尾指针同时置 0
}
//判断队列为空
bool IsEmpty(LinkQueue *LQ) {
if(!LQ) return 0; //不为空
if (LQ->front == NULL)
{
return true;
}
return false;
}
//判断队列是否为满
bool IsFull(LinkQueue *LQ) {
if(!LQ) return false; //不为空
if (LQ->length == MaxSize) {
return true;
}
return false;
}
//入队,将元素 data 插入到队列 LQ 中
bool EnterQueue(LinkQueue *LQ,DataType data){
if(!LQ) return false;
if(IsFull(LQ)){
cout<<"无法插入元素 "<<data<<", 队列已满!"<<endl;
return false;
}
QNode *qNode = new QNode;//分配新节点
qNode->data = data;
qNode->next = NULL; //将新节点的next指针置为空(先进先出原则)
if(IsEmpty(LQ)){
//空队列(新插入节点为首节点)
LQ->front = LQ->rear = qNode;//此插入节点为第一个节点也是最后一个节点
}else {
LQ->rear->next =qNode;//在队尾插入节点 qNode(队尾节点next指针指向新节点--实现插入)
LQ->rear = qNode; //队尾指向新插入的节点(队尾指针指向新节点为尾节点)
}
LQ->length++;//队列长度加1
return true;
}
//出队,将队列中队头的元素出队,其后的第一个元素成为新的队首
bool DeleteQueue(LinkQueue *LQ, DataType *data){
QNode * tmp = NULL;//临时变量,用来保存要被释放掉资源的队首
if (!LQ || IsEmpty(LQ)) {
cout << "队列为空!" << endl;
return false;
}
if (!data) return false;
tmp = LQ->front; //保存队首节点
LQ->front = tmp->next;//将队首指针指向原首节点的下一个节点
if (!LQ->front) LQ->rear = NULL;//如果队头出列后不存在其他元素,则 rear 节点也要置空
*data = tmp->data;
LQ->length--; //队列长度减1
delete tmp; //释放内存
return true;
}
//打印队列中的各元素
void PrintQueue(LinkQueue *LQ) {
QueuePtr tmp;
if(!LQ) return ;
if(LQ->front==NULL){
cout<<"队列为空!";
return ;
}
tmp = LQ->front;
while(tmp) {
cout<<setw(4)<<tmp->data;
tmp = tmp->next;
}
cout<<endl;
}
//获取队首元素,不出队
bool GetHead(LinkQueue *LQ,DataType *data) {
if (!LQ || IsEmpty(LQ)){
cout << "队列为空!" << endl;
return false;
}
if (!data) return false;
*data = LQ->front->data;
return true;
}
//清空队列
void ClearQueue(LinkQueue *LQ) {
if(!LQ) return ;
while(LQ->front){
QueuePtr tmp = LQ->front->next;
delete LQ->front;
LQ->front = tmp;
}
LQ->front = LQ->rear = NULL;
LQ->length = 0;
}
//获取队列中元素的个数
int getLength(LinkQueue* LQ){
if(!LQ) return 0;
return LQ->length;
}
int main() {
LinkQueue *LQ = new LinkQueue;
DataType data = -1;
//初始化队列
InitQueue(LQ);
//入队
for(int i=0; i<7; i++){
EnterQueue(LQ, i);
}
//打印队列中的元素
printf("队列中的元素(总共%d 个):", getLength(LQ));
PrintQueue(LQ);
cout << endl;
//出队
//for(int i=0; i<10; i++){
if(DeleteQueue(LQ, &data)){
cout<<"出队的元素是:"<<data<<endl;
}else {
cout<<"出队失败!"<<endl;
}
//}
//打印队列中的元素
printf("出队一个元素后,队列中剩下的元素[%d]:", getLength(LQ));
PrintQueue(LQ);
cout<<endl;
ClearQueue(LQ);
cout<<"清空队列!\n";
PrintQueue(LQ);
//清理资源
delete LQ;
system("pause");
return 0;
}