数据结构之链队列

一.引入

        链队列是在单链表的基础上做了简单的修改,为了使空队列和非空队列的操作一致,链队列也加上头结点。根据队列的先进先出特性,为了操作上的方便,设置队头指针指向链队列的头结点,队尾指针指向终端结点。


二.算法设计

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;
}

五.运行结果




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值