数据结构实现 2.3:链表队列(C++版)

1. 概念及基本框架

在前面第三节中,我们通过 动态数组 实现了 队列 这种数据结构。当然,队列也可以通过 链表 来实现所谓的 链表队列

链表队列

链表队列的结构如上图所示,链表队列有着队列的基本特性:
1.队列队头队尾 两端。
2.入队 操作只能从 队尾 进行,出队 操作只能从 队头 进行。
3.先 入队 的先 出队 ,即 先进先出(First In First Out),FIFO
因为链表对链表末端操作时间复杂度较大,所以添加了一个 tail 指针,使得原来 O(n) 的时间复杂度变成了 O(1) 级别的。由于 tail 指针的加入,而且我们的操作也只针对 headtail ,所以可以去掉虚拟头结点,因此我们需要从底层来重新构建这个类。
与数组队列类似,可以利用一个由 纯虚函数 构成的 抽象类 作为一个接口来定义这些操作。具体代码如下:

template <class T>
class Queue{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入队操作
	virtual void enqueue(T num) = 0;
	//出队操作
	virtual void dequeue() = 0;
	//获得队首元素
	virtual T front() = 0;
};

下面只需要通过继承 抽象类,并且重写 纯虚函数 ,就可以完成 链表队列 的实现。链表队列类的框架如下:

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	LinkedListQueue(){
		head = NULL;
		tail = NULL;
		m_size = 0;
	}
	...
private:
	Node<T> *head;
	Node<T> *tail;
	int m_size;
};

其中的 Node 类是第五节链表中定义的一个类,这里不再重复定义,直接使用,Node 类的定义如下:

template <class T>
class Node{
public:
	Node(T num = NULL, Node *next = NULL){
		m_data = num;
		this->next = next;
	}
public:
	T m_data;
	Node *next;
};

LinkedListQueue 类内部定义头指针、尾指针以及链表长度,为了保护数据,把变量都放在 private 部分,为了兼容更多类型,这里使用了泛型的概念。

2. 基本操作程序实现

2.1 入队操作

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	...
	//入队操作
	void enqueue(T num){
		if (head == NULL){
			head = new Node<T>(num, NULL);
			tail = head;
		}
		else{
			tail->next = new Node<T>(num, NULL);
			tail = tail->next;
		}
		m_size++;
	}
	...
};

由于使用了尾指针,入队操作十分方便。但是要注意,当链表为空时的特殊情况。

2.2 出队操作

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	...
	//出队操作
	void dequeue(){
		if (m_size <= 0){
			cout << "出队失败!" << endl;
			return;
		}
		Node<T> *node = head->next;
		delete head;
		head = node;
		m_size--;
	}
	...
};

2.3 查找操作

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	...
	//获得队首元素
	T front(){
		if (m_size <= 0){
			cout << "队列为空!" << endl;
			return NULL;
		}
		return head->m_data;
	}
	...
};

队列只能获得队首元素。

2.4 其他操作

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	...
	int size(){
		return m_size;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		Node<T> *node = head;
		cout << "LinkedListQueue: ";
		cout << "Size = " << m_size << endl;
		cout << "front ";
		while (node){
			cout << node->m_data << "->";
			node = node->next;
		}
		cout << "NULL rear" << endl;
	}
	...
};

3. 算法复杂度分析

3.1 入队操作

函数 最坏复杂度 平均复杂度
enqueue O(1) O(1)

3.2 出队操作

函数 最坏复杂度 平均复杂度
dequeue O(1) O(1)

3.3 查找操作

函数 最坏复杂度 平均复杂度
front O(1) O(1)

总体情况:

操作 时间复杂度
O(1)
O(1)
O(1)

由此可以看出,链表队列操作的增、删、查都是 O(1) 级别的时间复杂度。
注:队列并不提供改的操作。

4. 完整代码

Node类 代码:

template <class T>
class Node{
public:
	Node(T num = NULL, Node *next = NULL){
		m_data = num;
		this->next = next;
	}
public:
	T m_data;
	Node *next;
};

抽象类 接口代码:

#ifndef __QUEUE_H__
#define __QUEUE_H__

template <class T>
class Queue{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入队操作
	virtual void enqueue(T num) = 0;
	//出队操作
	virtual void dequeue() = 0;
	//获得队首元素
	virtual T front() = 0;
};

#endif

链表队列 代码:

#ifndef __LINKEDLISTQUEUE_H__
#define __LINKEDLISTQUEUE_H__

#include "Queue.h"

using namespace std;

template <class T>
class LinkedListQueue : public Queue<T>{
public:
	LinkedListQueue(){
		head = NULL;
		tail = NULL;
		m_size = 0;
	}
	int size(){
		return m_size;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		Node<T> *node = head;
		cout << "LinkedListQueue: ";
		cout << "Size = " << m_size << endl;
		cout << "front ";
		while (node){
			cout << node->m_data << "->";
			node = node->next;
		}
		cout << "NULL rear" << endl;
	}
	//入队操作
	void enqueue(T num){
		if (head == NULL){
			head = new Node<T>(num, NULL);
			tail = head;
		}
		else{
			tail->next = new Node<T>(num, NULL);
			tail = tail->next;
		}
		m_size++;
	}
	//出队操作
	void dequeue(){
		if (m_size <= 0){
			cout << "出队失败!" << endl;
			return;
		}
		Node<T> *node = head->next;
		delete head;
		head = node;
		m_size--;
	}
	//获得队首元素
	T front(){
		if (m_size <= 0){
			cout << "队列为空!" << endl;
			return NULL;
		}
		return head->m_data;
	}
private:
	Node<T> *head;
	Node<T> *tail;
	int m_size;
};

#endif

猜你喜欢

转载自blog.csdn.net/qq_35481167/article/details/83932728
今日推荐