数据结构实现(六):链表栈(C++版)

1. 概念及基本框架

通过第五节,我们知道链表虽然整体的操作时间复杂度是 O(n) 级别的,但是如果只对头结点进行操作,那么时间复杂度是 O(1) 级别的,这很类似于栈(单口容器)的操作。
在第二节中,我们利用 数组 实现了 这种数据结构。当然,栈也可以通过 链表 来实现。下面通过链表来实现 链表栈

链表栈
链表栈的结构如上图所示,链表栈有着栈的基本特性:
1.栈顶栈底 两端。
2.入栈出栈 操作只能从 栈顶 进行。
3.后 入栈 的先 出栈 ,即 后进先出(Last In First Out),LIFO
与数组栈类似,依旧使用由 纯虚函数 构成的 抽象类 作为一个接口来定义栈的基本操作。具体代码如下:

template <class T>
class Stack{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入栈操作
	virtual void push(T num) = 0;
	//出栈操作
	virtual void pop() = 0;
	//获得栈顶元素
	virtual T peek() = 0;
};

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

template <class T>
class LinkedListStack : public Stack<T>{
public:
	LinkedListStack(){}
	...
private:
	LinkedList<T> list;
};

这个类内部定义一个链表类对象,为了保护数据,把它放在 private 部分。因为 LinkedListStack 类包含了 LinkedList 类,所以构造函数 LinkedListStack 会自动调用 LinkedList 的构造函数。为了兼容更多类型,这里使用了泛型的概念。

2. 基本操作程序实现

2.1 入栈操作

template <class T>
class LinkedListStack : public Stack<T>{
public:
	...
	//入栈操作
	void push(T num){
		list.addFirst(num);
	}
	...
};

入栈操作使用了链表的增加第一个元素的操作来实现。

2.2 出栈操作

template <class T>
class LinkedListStack : public Stack<T>{
public:
	...
	//出栈操作
	void pop(){
		list.removeFirst();
	}
	...
};

出栈操作使用了链表的删除第一个元素的操作来实现。

2.3 查找操作

template <class T>
class LinkedListStack : public Stack<T>{
public:
	...
	//获得栈顶元素
	T peek(){
		return list.get(0);
	}
	...
};

因为栈只能获得栈顶元素,所以这里的查找操作也非常简单。

2.4 其他操作

template <class T>
class LinkedListStack : public Stack<T>{
public:
	...
	int size(){
		return list.size();
	}
	bool isEmpty(){
		return list.isEmpty();
	}
	void print(){
		cout << "LinkedListStack: ";
		cout << "Size = " << list.size() << endl;
		cout << "top ";
		for (int i = 0; i < list.size(); ++i){
			cout << list.get(i) << "->";
		}
		cout << "NULL" << endl;
	}
	...
};

3. 算法复杂度分析

3.1 入栈操作

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

3.2 出栈操作

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

3.3 查找操作

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

总体情况:

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

因为都是针对第一个元素的操作,链表栈操作都是 O(1) 级别的时间复杂度,而且相较数组栈而言,省去了扩容(缩容)操作。
注:这里并没有改的操作,如果更改,需要先出栈,再入栈。

4. 完整代码

链表类 代码:

#ifndef __LINKEDLIST_H__
#define __LINKEDLIST_H__

using namespace std;

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;
};
template <class T>
class LinkedList{
public:
	LinkedList(){
		head.m_data = NULL;
		head.next = NULL;
		m_size = 0;
	}
	int size(){
		return m_size;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		cout << "LinkedList: ";
		cout << "Size = " << m_size << endl;
		Node<T> *node = head.next;
		while(node){
			cout << node->m_data << "->";
			node = node->next;
		}
		cout << "NULL" << endl;
	}
	//增加操作
	void add(int index, T num);
	void addFirst(T num);
	void addLast(T num);
	//删除操作
	T remove(int index);
	T removeFirst();
	T removeLast();
	void removeElement(T num);
	//修改操作
	void set(int index, T num);
	//查找操作
	T get(int index);
	T getFirst();
	T getLast();
	bool contains(T num);
private:
	Node<T> head;
	int m_size;
};

template <class T>
void LinkedList<T>::add(int index, T num){
	if (index < 0 || index > m_size){
		cout << "添加位置非法!" << endl;
		return;
	}
	Node<T> *node = &head;
	for (int i = 0; i < index; ++i, node = node->next);
	node->next = new Node<T>(num, node->next);
	m_size++;
}
template <class T>
void LinkedList<T>::addFirst(T num){
	add(0, num);
}
template <class T>
void LinkedList<T>::addLast(T num){
	add(m_size, num);
}

template <class T>
T LinkedList<T>::remove(int index){
	if (index < 0 || index >= m_size){
		cout << "删除位置非法!" << endl;
		return NULL;
	}
	Node<T> *node = &head;
	for (int i = 0; i < index; ++i, node = node->next);
	Node<T> *p = node->next;
	T res = p->m_data;
	node->next = p->next;
	delete p;
	m_size--;
	return res;
}
template <class T>
T LinkedList<T>::removeFirst(){
	return remove(0);
}
template <class T>
T LinkedList<T>::removeLast(){
	return remove(m_size - 1);
}
template <class T>
void LinkedList<T>::removeElement(T num){
	Node<T> *node = &head;
	Node<T> *p;
	while(node){
		p = node->next;
		if (p->m_data == num){
			node->next = p->next;
			delete p;
			m_size--;
			return;
		}
		node = p;
	}
}

template <class T>
void LinkedList<T>::set(int index, T num){
	Node<T> *node = head.next;
	for (int i = 0; i < index; ++i, node = node->next);
	node->m_data = num;
}

template <class T>
T LinkedList<T>::get(int index){
	if (index < 0 || index >= m_size){
		cout << "访问位置非法!" << endl;
		return NULL;
	}
	Node<T> *node = head.next;
	for (int i = 0; i < index; ++i, node = node->next);
	return node->m_data;
}

template <class T>
T LinkedList<T>::getFirst(){
	return get(0);
}
template <class T>
T LinkedList<T>::getLast(){
	return get(m_size - 1);
}
template <class T>
bool LinkedList<T>::contains(T num){
	Node<T> *node = head.next;
	while(node){
		if (node->m_data == num){
			return true;
		}
		node = node->next;
	}
	return false;
}

#endif

抽象类 接口代码:

#ifndef __STACK_H__
#define __STACK_H__

template <class T>
class Stack{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	virtual void print() = 0;
	//入栈操作
	virtual void push(T num) = 0;
	//出栈操作
	virtual void pop() = 0;
	//获得栈顶元素
	virtual T peek() = 0;
};

#endif

链表栈 代码:

#ifndef __LINKEDLISTSTACK_H__
#define __LINKEDLISTSTACK_H__

#include "LinkedList.h"
#include "Stack.h"

template <class T>
class LinkedListStack : public Stack<T>{
public:
	LinkedListStack(){}
	int size(){
		return list.size();
	}
	bool isEmpty(){
		return list.isEmpty();
	}
	void print(){
		cout << "LinkedListStack: ";
		cout << "Size = " << list.size() << endl;
		cout << "top ";
		for (int i = 0; i < list.size(); ++i){
			cout << list.get(i) << "->";
		}
		cout << "NULL" << endl;
	}
	//入栈操作
	void push(T num){
		list.addFirst(num);
	}
	//出栈操作
	void pop(){
		list.removeFirst();
	}
	//获得栈顶元素
	T peek(){
		return list.get(0);
	}
private:
	LinkedList<T> list;
};

#endif

猜你喜欢

转载自blog.csdn.net/qq_35481167/article/details/83928493