資料結構實現(六):連結串列棧(C++版)
阿新 • • 發佈:2018-11-10
資料結構實現(六):連結串列棧(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