链队列的表示与实现如下图:
代码如下:
#include<iostream>
using namespace std;#define MAXQSIZE 100 //最大队列长度
typedef int QElemType; //typedef struct Qnode
{QElemType data;struct Qnode* next;
}QNode, *QueuePtr; //队列结点类型、指向队列结点的指针类型typedef struct //为指向队列结点的指针类型QueuePtr单独建立一个包含队头队尾的结构体
{QueuePtr front; //队头指针QueuePtr rear; //队尾指针
}LinkQueue; //链式队列定义//初始化链队列:front与rear都指向队头结点,队头结点next指针置空
bool InitQueue(LinkQueue& Q)
{//将队列的头尾指针都指向同一个节点,表示队列为空//C++ 的 new 运算符会在对象不再需要时自动调用析构函数,并释放内存,而 malloc 函数需要手动调用 free 函数来释放内存。Q.front = Q.rear = new QNode; //Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));if(!Q.front){exit(OVERFLOW);}Q.front->next = NULL; //将队列队头指针置空return true; //初始化完成
}
//链队列判空
bool QueueEmpty(LinkQueue& Q)
{//队头队尾指针指向同一位置(队头结点),队列为空。return Q.front == Q.rear;
}//链队列销毁:从队头结点开始,一次释放所有结点
bool DestoryQueue(LinkQueue& Q)
{QueuePtr temp; //创建临时指针 指针声明二选一//QNode* temp; while (Q.front){ //反正rear指针闲置无事,此处可以不额外创建temp,直接将下列temp替换成Q.rear效果一样。temp = Q.front->next; //temp指向队头的下一个结点delete Q.front; //释放队头结点Q.front = temp; //更新队头结点}Q.rear = NULL;cout << "队列销毁成功!" << endl;return true;
}
//链队入队操作,将元素value入队:创建新结点,将元素放入结点数据域、新节点next指针置空、队尾rear指向新结点、更新队尾结点。
bool EnQueue(LinkQueue& Q, QElemType value)
{QueuePtr temp = new QNode; //创建指针型QNode结点,指针指向要插入的结点元素if (!temp) //创建结点,分配内存要判断是否分配成功{exit(OVERFLOW);}temp->data = value; //将要插入的元素放入temp结点数据域temp->next = NULL; //temp结点指针域置空Q.rear->next = temp; //将队尾指针接上temp结点Q.rear = temp; //更新队尾结点return true;
}
//链队的出队:删除队头结点的下一位,头结点不存储数据元素。
//判断链队列是否为空、创建temp指针指向要出栈的元素、删除该结点,将头结点指向删除结点的后继结点,更新队头,若删除的是队尾,则队头队尾指针均指向队头结点。。
bool DeQueue(LinkQueue& Q, QElemType value)
{if (!QueueEmpty(Q)) //若链队列不为空{QueuePtr temp = NULL; //创建指针类型的QNode结点,指针指向新结点if (!temp) exit(OVERFLOW);//判断新结点内存是否分配成功temp = Q.front->next;//temp指向队头结点下一位即第一位元素value = temp->data;//将temp所指结点的数据保存到value中Q.front->next = temp->next;//更新队头结点if (Q.rear == temp)//如果删除的是最后一个结点(尾结点),尾结点回移{Q.rear = Q.front;//rear、front均指向仅存的头结点Q.front->next = NULL;}delete temp; //释放出栈元素所占结点空间return true; //出栈成功}return false; //队列为空
}
//链队的队头元素
bool GetHead(LinkQueue Q)
{if (!QueueEmpty(Q)) //若链队列不为空{return Q.front->next->data;}return false;
}
//链队列的长度/元素个数
//这里Q不能用'&'引用型传递,否则下方队头指针front的移动会修改原队列front指针。不加引用,就会创建一个副本执行操作,故相比前者会多消耗些内存和时间。也可以创建一个临时指针temp对队列进行遍历,这样即使Q加了&, 也不会影响原链队列。
int QueueLength(LinkQueue Q)
{if (!QueueEmpty(Q)) //若链队列不为空{int count = 0; //元素个数/队列长度while (Q.front != Q.rear)//直到{Q.front = Q.front->next;//队头指针后移一位count++; //计数加一}return count; }return false; //队列为空或不存在
}
//遍历输出链队元素
bool QueuePrint(LinkQueue Q)
{if (!QueueEmpty(Q)){while (Q.front != Q.rear){Q.front = Q.front->next; //将链队头指针指向第一个元素结点cout << Q.front->data <<" "; //输出该结点所指的结点数据}cout << endl;return true; }cout << "队列为空或不存在!";return false;
}int main()
{LinkQueue Q;//QElemType value;InitQueue(Q);int number = 0; //入队的元素个数cout << "请输入要入队的元素个数:" << " ";cin >> number; int num = 0; //入队的数据元素while ((number--) > 0){cin >> num; //输入数据元素EnQueue(Q, num); //将num入队 }cout << "队列输出顺序:";QueuePrint(Q); //遍历输出队列元素cout << "队头元素为:" << GetHead(Q) << endl;cout << "队列长度为:" << QueueLength(Q) << endl;DestoryQueue(Q);//销毁链式队列,释放内存空间QueuePrint(Q); //遍历队列元素system("pause");return 0;
}
结果如下: