一.引入
链队列是在单链表的基础上做了简单的修改,为了使空队列和非空队列的操作一致,链队列也加上头结点。根据队列的先进先出特性,为了操作上的方便,设置队头指针指向链队列的头结点,队尾指针指向终端结点。
二.算法设计
LinkedQueue.h
#ifndef SRC_LINKEDQUEUE_H_
#define SRC_LINKEDQUEUE_H_
/*
* 结点:
* data:数据域,存储数据元素
* next:指针域,存储该结点的后继结点的地址
*/
template <class T>
struct Node{
T data;
Node<T> *next;
};
template <class T>
class LinkedQueue {
public:
LinkedQueue();//无参构造器
LinkedQueue(T array[],int length);//有参构造器
virtual ~LinkedQueue();//析构函数
int getLength();//取当前队的长度
void enqueue(T value);//入队
T dequeue();//出队
T getHead();//取队头元素
void getAll();//遍历队的全部元素
bool isEmpty();//判断是否队空
private:
Node<T> *front;//队头指针,指向头结点(注意:不是队头,而是队头的前一个结点,该结点的 next 域存储的是队头的位置)
Node<T> *rear;//队尾指针,指向队尾
int length;//当前队的长度
};
#endif
三.详细设计(C++)
LinkedQueue.cpp
#include "LinkedQueue.h"
#include <iostream>
using namespace std;
/*
* 无参构造器:
* 1.创建一个头结点 head ,申请空间
* 2.把头结点 head 的 next 置为 NULL
* 3.队头指针 front 指向头结点 head
* 4.队尾指针 rear 指向头结点 head
* 5.当前队的长度置为 0
*/
template <class T>
LinkedQueue<T>::LinkedQueue(){
Node<T> *head = new Node<T>;
head->next = NULL;
front = head;
rear = head;
length = 0;
}
/*
* 有参构造器:
* 1.创建一个头结点 head ,申请空间
* 2.把头结点 head 的 next 置为 NULL
* 3.队头指针 front 指向头结点 head
* 4.队尾指针 rear 指向头结点 head
* 5.当前队的长度置为 0
* 6.创建一个结点 node ,置为 NULL
* 7.循环:
* ①.为结点 node 申请空间
* ②.把数组的值存储在结点 node 的 data 域中
* ③.把结点 node 的 next 域置为 NULL
* ④.把原队尾结点的 next 置为结点 node 的地址,即原队尾结点与结点 node 相连
* ⑤.队尾指针 rear 指向结点 node ,即结点 node 成为队尾结点
* 8.记录当前队的长度
*/
template <class T>
LinkedQueue<T>::LinkedQueue(T array[],int length){
Node<T> *head = new Node<T>;
head->next = NULL;
front = head;
rear = head;
Node<T> *node = NULL;
for(int i = 0;i < length;i++){
node = new Node<T>;
node->data = array[i];
node->next = NULL;
rear->next = node;
rear = node;
}
this->length = length;
}
/*
* 析构函数:
* 1.创建一个结点 deleteNode ,置为 NULL
* 2.循环:
* ①.结点 deleteNode 指向队头
* ②.队头指针 front 指向队头的下一个结点
* ③.判断结点 deleteNode 是否是队尾,若是则队尾指针 rear 和队头指针 front 指向同一个结点,即头结点
* ④.删除结点 deleteNode ,即队头
* ⑤.当前队的长度减一
* 3.删除头结点
*/
template <class T>
LinkedQueue<T>::~LinkedQueue(){
Node<T> *deleteNode = NULL;
while(!isEmpty()){
deleteNode = front->next;
front->next = deleteNode->next;
if(deleteNode->next == NULL){
rear = front;
}
delete deleteNode;
length--;
}
delete front;
}
/*
* 取当前队的长度:
* 返回当前队的长度
*/
template <class T>
int LinkedQueue<T>::getLength(){
return length;
}
/*
* 入队:
* 1.创建一个结点 enNode ,申请空间
* 2.把 value 存储在结点 enNode 的 data 域中
* 3.结点 enNode 的 data 域置为 NULL
* 4.原队尾结点的 next 域置为结点 enNode 的地址,即原队尾结点与结点 enNode 相连
* 5.队尾指针 rear 指向结点 enNode ,即结点 enNode 成为新队尾
* 6.当前队的长度加一
*/
template <class T>
void LinkedQueue<T>::enqueue(T value){
Node<T> *enNode = new Node<T>;
enNode->data = value;
enNode->next = NULL;
rear->next = enNode;
rear = enNode;
length++;
}
/*
* 出队:
* 1.判断是否队空,若是返回 -1,否则
* 2.创建一个结点 head ,其指向队头
* 3.定义一个变量 headValue ,其记录队头结点存储的元素
* 4.队头指针 front 的 next 域置为原队头的下一个结点的地址,即头结点与新队头相连
* 5.判断原队头是否也是队尾,即当前队是否只剩下一个结点(不包括头结点),若是则队尾指针 rear 和队头指针 front 指向同一个结点,即头结点
* 6.删除原队头
* 7.当前队的长度减一
* 8.返回原队头存储的元素 headValue
*/
template <class T>
T LinkedQueue<T>::dequeue(){
if(isEmpty()){
cout<<"队空!"<<endl;
return -1;
}
Node<T> *head = front->next;
T headValue = head->data;
front->next = head->next;
if(head->next == NULL){
rear = front;
}
delete head;
length--;
return headValue;
}
/*
* 取队头元素:
* 1.判断是否队空,若是返回 -1,否则
* 2.返回队头结点存储的元素
* 注意:不删除队头结点
*/
template <class T>
T LinkedQueue<T>::getHead(){
if(isEmpty()){
cout<<"队空!"<<endl;
return -1;
}
return front->next->data;
}
/*
* 遍历队的全部元素:
* 1.判断是否队空,若是返回,否则
* 2.创建一个结点 p ,其指向队头
* 3.循环:当未到达队尾时
* ①.输出结点 p 指向的结点存储的元素
* ②.结点 p 指向下一个结点
* 4.输出队尾结点存储的元素
*/
template <class T>
void LinkedQueue<T>::getAll(){
if(isEmpty()){
cout<<"队空!"<<endl;
return;
}
Node<T> *p = front->next;
while(p->next != NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<p->data<<endl;
}
/*
* 判断是否队空:
* 若队头结点 front 和队尾结点 rear 指向同一个结点,即头结点,则返回 true ,否则返回 false
*/
template <class T>
bool LinkedQueue<T>::isEmpty(){
return front == rear ? true : false;
}
四.测试
TestLinkedQueue.cpp
#include "LinkedQueue.h"
#include "LinkedQueue.cpp"
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
int arr[] = {0,1,2,3,4};
cout<<"创建对象:0、1、2、3、4 依次入队 "<<endl;
LinkedQueue<int> linkedQueue(arr,5);
cout<<"遍历队内的元素:";
linkedQueue.getAll();
cout<<"当前队的长度:";
cout<<linkedQueue.getLength()<<endl;
cout<<"当前的队头元素:"<<linkedQueue.getHead()<<endl;
cout<<endl;
while(!linkedQueue.isEmpty()){
cout<<linkedQueue.dequeue()<<"出队!"<<endl;
cout<<"遍历队内的元素:";
linkedQueue.getAll();
cout<<"当前队的长度:";
cout<<linkedQueue.getLength()<<endl;
cout<<"当前的队头元素:"<<linkedQueue.getHead()<<endl;
cout<<endl;
}
cout<<endl;
for(int i = 0;i < 10;i++){
cout<<i<<"入队!"<<endl;
linkedQueue.enqueue(i);
}
cout<<"遍历队内的元素:";
linkedQueue.getAll();
cout<<"当前队的长度:";
cout<<linkedQueue.getLength()<<endl;
cout<<"当前的队头元素:"<<linkedQueue.getHead()<<endl;
cout<<endl;
cout<<"销毁队!"<<endl;
linkedQueue.~LinkedQueue();
return 0;
}
五.运行结果