資料結構實現 5.1:對映_基於樹實現(C++版)
資料結構實現 5.1:對映_基於樹實現(C++版)
1. 概念及基本框架
對映 是一種高階資料結構,其實現方法也不唯一,但儲存上使用 鏈式儲存(即記憶體的物理空間是不連續的)。這一節我們通過 二分搜尋樹
對映 的基本特性:
1.對映內元素包含 鍵(key) 和 值(value) ,而且一一對應。
2.對映內的元素的鍵 不能重複 。
注:有些對映(多重對映)中元素的鍵也可以重複。
顯然,二分搜尋樹滿足對映的特性,所以我們嘗試利用二分搜尋樹來實現對映。但是,在 3.1 中實現的二分搜尋樹結點只有一個數據,所以我們需要從底層進行一些改進去適應對映這一資料結構。首先來定義樹的結點類:
template <class K, class V>
class MapBSTNode{
public:
MapBSTNode(K key = NULL, V value = NULL, MapBSTNode<K, V> *left = NULL, MapBSTNode<K, V> *right = NULL){
m_key = key;
m_value = value;
this->left = left;
this->right = right;
}
public:
K m_key;
V m_value;
MapBSTNode<K, V> *left;
MapBSTNode<K, V> *right;
};
這個結點類的內部也顯式的給出了建構函式,下面通過結點類來建立一棵二叉樹。這個過程和 3.1
template <class K, class V>
class MapBST{
public:
MapBST(){
root = NULL;
}
...
private:
MapBSTNode<K, V> *root;
int m_size;
};
為了滿足對映操作的需求,我為這個類定義了幾個介面函式,實現方法與 3.1 類似,所以同樣不再贅述。
template <class K, class V>
class MapBST{
public:
...
int size(){
return m_size;
}
bool isEmpty(){
return root == NULL;
}
//增加操作
void add(K key, V value){
root = add(root, key, value);
}
//刪除操作
V remove(K key){
V res = get(key);
root = remove(root, key);
return res;
}
//修改操作
void set(K key, V value){
MapBSTNode<K, V> *node = root;
while (node){
if (key == node->m_key){
node->m_value = value;
return;
}
else if (key < node->m_key){
node = node->left;
}
else{
node = node->right;
}
}
cout << "不存在" << key << '!' << endl;
return;
}
//查詢操作
V get(K key){
MapBSTNode<K, V> *node = root;
while (node){
if (key == node->m_key){
return node->m_value;
}
else if (key < node->m_key){
node = node->left;
}
else{
node = node->right;
}
}
cout << "不存在" << key << '!' << endl;
return NULL;
}
bool contains(K key){
return contains(root, key);
}
private:
MapBSTNode<K, V>* add(MapBSTNode<K, V> *node, K key, V value){
if (node == NULL){
m_size++;
return new MapBSTNode<K, V>(key, value);
}
else if (key < node->m_key){
node->left = add(node->left, key, value);
}
else if (key > node->m_key){
node->right = add(node->right, key, value);
}
return node;
}
MapBSTNode<K, V>* remove(MapBSTNode<K, V> *node, K key){
if (node == NULL){
return node;
}
if (key < node->m_key){
node->left = remove(node->left, key);
}
else if (key > node->m_key){
node->right = remove(node->right, key);
}
else if (key == node->m_key){
if (node->left == NULL){
MapBSTNode<K, V> *rightNode = node->right;
delete node;
m_size--;
return rightNode;
}
else if (node->right == NULL){
MapBSTNode<K, V> *leftNode = node->left;
delete node;
m_size--;
return leftNode;
}
else{
MapBSTNode<K, V> *minNode = node->right;
for (; minNode->left; minNode = minNode->left);
node->m_key = minNode->m_key;
node->right = remove(node->right, minNode->m_key);
return node;
}
}
return node;
}
bool contains(MapBSTNode<K, V> *node, K key){
if (node == NULL){
return false;
}
if (key == node->m_key){
return true;
}
else if (key < node->m_key){
return contains(node->left, key);
}
else{
return contains(node->right, key);
}
}
...
};
有了改進版的二分搜尋樹,我們就可以利用一個由 純虛擬函式 構成的 抽象類 作為一個介面來定義這些操作。具體程式碼如下:
template <class K, class V>
class Map{
public:
virtual int size() = 0;
virtual bool isEmpty() = 0;
//增加操作
virtual void add(K key, V value) = 0;
//刪除操作
virtual V remove(K key) = 0;
//修改操作
virtual void set(K key, V value) = 0;
//查詢操作
virtual bool contains(K key) = 0;
virtual V get(K key) = 0;
};
下面只需要通過繼承 抽象類,並且重寫 純虛擬函式 ,就可以完成 對映 的實現。對映類的框架如下:
template <class K, class V>
class BSTMap : public Map<K, V>{
...
private:
MapBST<K, V> bst;
};
這裡為了避免重複設計就可以相容更多資料型別,引入了 泛型 ,即 模板 的概念。(模板的關鍵字是 class 或 typename)
這裡的 bst 表示一棵 二分搜尋樹 ,同樣,為了保護資料,變數設定為 private 。
注:這裡沒有顯式的給出建構函式,因為子類中除了二分搜尋樹物件之外沒有特別需要初始化的東西。編譯器會預設先呼叫 二分搜尋樹 類(即父類)的建構函式,再去呼叫 對映 類(即子類)的建構函式。
實現了前面的程式之後,接下來就是一個對映的增、刪、改、查以及一些其他基本操作,接下來利用程式碼去實現。
2. 基本操作程式實現
2.1 增加操作
template <class K, class V>
class BSTMap : public Map<K, V>{
public:
...
//增加操作
void add(K key, V value){
bst.add(key, value);
}
...
};
直接呼叫二分搜尋樹的增加操作。(因為二分搜尋樹中的元素本來就不重複)
2.2 刪除操作
template <class K, class V>
class BSTMap : public Map<K, V>{
public:
...
//刪除操作
V remove(K key){
return bst.remove(key);
}
...
};
直接呼叫二分搜尋樹的刪除操作。
2.3 修改操作
template <class K, class V>
class BSTMap : public Map<K, V>{
public:
...
//修改操作
void set(K key, V value){
bst.set(key, value);
}
...
};
2.4 查詢操作
template <class K, class V>
class BSTMap : public Map<K, V>{
public:
...
//查詢操作
bool contains(K key){
return bst.contains(key);
}
V get(K key){
return bst.get(key);
}
...
};
2.5 其他操作
對映還有一些其他的操作,包括 對映大小 的查詢等操作。
template <class K, class V>
class BSTMap : public Map<K, V>{
public:
int size(){
return bst.size();
}
bool isEmpty(){
return bst.isEmpty();
}
...
};
3. 演算法複雜度分析
因為對映操作直接呼叫了二分搜尋樹的操作,所以其操作的時間複雜度和二分搜尋樹相同。
3.1 增加操作
函式 | 最壞複雜度 | 平均複雜度 |
---|---|---|
add | O(n) | O(logn) |
3.2 刪除操作
函式 | 最壞複雜度 | 平均複雜度 |
---|---|---|
remove | O(n) | O(logn) |
3.3 修改操作
函式 | 最壞複雜度 | 平均複雜度 |
---|---|---|
set | O(n) | O(logn) |
3.4 查詢操作
函式 | 最壞複雜度 | 平均複雜度 |
---|---|---|
contains | O(n) | O(logn) |
get | O(n) | O(logn) |
總體情況:
操作 | 時間複雜度 |
---|---|
增 | O(logn) |
刪 | O(logn) |
改 | O(logn) |
查 | O(logn) |
很顯然,利用二分搜尋樹很容易實現對映這一高階資料結構。
4. 完整程式碼
程式完整程式碼(這裡使用了標頭檔案的形式來實現類)如下。
二分搜尋樹 類程式碼:
#ifndef __MAPBST_H__
#define __MAPBST_H__
template <class K, class V>
class MapBSTNode{
public:
MapBSTNode(K key = NULL, V value = NULL, MapBSTNode<K, V> *left = NULL, MapBSTNode<K, V> *right = NULL){
m_key = key;
m_value = value;
this->left = left;
this->right = right;
}
public:
K m_key;
V m_value;
MapBSTNode<K, V> *left;
MapBSTNode<K, V> *right;
};
template <class K, class V>
class MapBST{
public:
MapBST(){
root = NULL;
}
int size(){
return m_size;
}
bool isEmpty(){
return root == NULL;
}
//增加操作
void add(K key, V value){
root = add(root, key, value);
}
//刪除操作
V remove(K key){
V res = get(key);
root = remove(root, key);
return res;
}
//修改操作
void set(K key, V value){
MapBSTNode<K, V> *node = root;
while (node){
if (key == node->m_key){
node->m_value = value;
return;
}
else if (key < node->m_key){
node = node->left;
}
else{
node = node->right;
}
}
cout << "不存在" << key << '!' << endl;
return;
}
//查詢操作
V get(K key){
MapBSTNode<K, V> *node = root;
while (node){
if (key == node->m_key){
return node->m_value;
}
else if (key < node->m_key){
node = node->left;
}
else{
node = node->right;
}
}
cout << "不存在" << key << '!' << endl;
return NULL;
}
bool contains(K key){
return contains(root, key);
}
private:
MapBSTNode<K, V>* add(MapBSTNode<K, V> *node, K key, V value){
if (node == NULL){
m_size++;
return new MapBSTNode<K, V>(key, value);
}
else if (key < node->m_key){
node->left = add(node->left, key, value);
}
else if (key > node->m_key){
node->right = add(node->right, key, value);
}
return node;
}
MapBSTNode<K, V>* remove(MapBSTNode<K, V> *node, K key){
if (node == NULL){
return node;
}
if (key < node->m_key){
node->left = remove(node->left, key);
}
else if (key > node->m_key){
node->right = remove(node->right, key);
}
else if (key == node->m_key){
if (node->left == NULL){
MapBSTNode<K, V> *rightNode = node->right;
delete node;
m_size--;
return rightNode;
}
else if (node->right == NULL){
MapBSTNode<K, V> *leftNode = node->left;
delete node;
m_size--;
return leftNode;
}
else{
MapBSTNode<K, V> *minNode = node->right;
for (; minNode->left; minNode = minNode->left);
node->m_key = minNode->m_key;
node->right = remove(node->right, minNode->m_key);
return node;
}
}
return node;
}
bool contains(MapBSTNode<K, V> *node, K key){
if (node == NULL){
return false;
}
if (key == node->m_key){
return true;
}
else if (key < node->m_key){
return contains(node->left, key);
}
else{
return contains(node->right, key);
}
}
private:
MapBSTNode<K, V> *root;
int m_size;
};
#endif
抽象類 介面程式碼:
#ifndef __MAP_H__
#define __MAP_H__
template <class K, class V>
class Map{
public:
virtual int size() = 0;
virtual bool isEmpty() = 0;
//增加操作
virtual void add(K key, V value) = 0;
//刪除操作
virtual V remove(K key) = 0;
//修改操作
virtual void set(K key, V value) = 0;
//查詢操作
virtual bool
相關推薦
資料結構實現 5.1:對映_基於樹實現(C++版)
資料結構實現 5.1:對映_基於樹實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 修改操作
2.4 查詢操作
2.5 其他操作
3. 演算法複
資料結構實現 5.2:對映_基於連結串列實現(C++版)
資料結構實現 5.2:對映_基於連結串列實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 修改操作
2.4 查詢操作
2.5 其他操作
3. 演
資料結構實現 10.2:對映_基於AVL樹實現(C++版)
資料結構實現 10.2:對映_基於AVL樹實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 修改操作
2.4 查詢操作
2.5 其他操作
3.
資料結構實現 4.1:集合_基於二分搜尋樹實現(C++版)
資料結構實現 4.1:集合_基於二分搜尋樹實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
資料結構實現 9.1:並查集_陣列結構實現(C++版)
資料結構實現 9.1:並查集_陣列結構實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 聯合操作
2.2 查詢操作
2.3 其他操作
3. 演算法複雜度分析
3.1 聯合操作
資料結構實現 6.1:二叉堆_基於動態陣列實現(C++版)
資料結構實現 6.1:二叉堆_基於動態陣列實現(C++版)
1. 概念及基本框架
1.1 滿二叉樹
1.2 完全二叉樹
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 查詢操作
資料結構實現 8.1:字典樹(C++版)
資料結構實現 8.1:字典樹(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 查詢操作
2.3 其他操作
3. 演算法複雜度分析
3.1 增加操作
3.2 查
資料結構實現 6.4:優先佇列_基於連結串列實現(C++版)
資料結構實現 6.4:優先佇列_基於連結串列實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入隊操作
2.2 出隊操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
資料結構實現 6.3:優先佇列_基於動態陣列實現(C++版)
資料結構實現 6.3:優先佇列_基於動態陣列實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入隊操作
2.2 出隊操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
資料結構實現 6.2:優先佇列_基於最大二叉堆實現(C++版)
資料結構實現 6.2:優先佇列_基於最大二叉堆實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入隊操作
2.2 出隊操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
資料結構實現 4.2:集合_基於連結串列實現(C++版)
資料結構實現 4.2:集合_基於連結串列實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
資料結構實現 3.1:二分搜尋樹(C++版)
資料結構實現 3.1:二分搜尋樹(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 查詢操作
2.4 遍歷操作
2.5 其他操作
3. 演算法複雜度分
資料結構實現 10.1:AVL樹(C++版)
資料結構實現 10.1:AVL樹(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.1.1 左左
2.1.2 右右
2.1.3 左右
2.1.4 右左
2.1
資料結構實現 9.2:並查集_樹思想實現(C++版)
資料結構實現 9.2:並查集_樹思想實現(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 聯合操作
2.2 查詢操作
2.3 其他操作
3. 演算法複雜度分析
3.1 聯合操作
【資料結構】5.1 順序表的查詢以及二分查詢的實現
類的結構如下:
class StaticSearchTable {
private:
int *data;
int data_number;
bool search_seq(int loc,int key);
void select_sort();
bool f
資料結構實現 2.1:連結串列(C++版)
1. 概念及基本框架
連結串列 是一種 線性結構 ,而且儲存上屬於 鏈式儲存(即記憶體的物理空間是不連續的),是線性表的一種。連結串列結構如下圖所示:
下面以一個我實現的一個簡單的連結串列類來進一步理解連結串列。
template <class T&g
資料結構實現(六):連結串列棧(C++版)
資料結構實現(六):連結串列棧(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入棧操作
2.2 出棧操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
3.1
資料結構實現(五):連結串列(C++版)
資料結構實現(五):連結串列(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 增加操作
2.2 刪除操作
2.3 修改操作
2.4 查詢操作
2.5 其他操作
3. 演算法複雜度分析
資料結構實現(四):迴圈佇列(C++版)
資料結構實現(四):迴圈佇列(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入隊操作
2.2 出隊操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
3.1 入
資料結構實現(三):陣列佇列(C++版)
資料結構實現(三):陣列佇列(C++版)
1. 概念及基本框架
2. 基本操作程式實現
2.1 入隊操作
2.2 出隊操作
2.3 查詢操作
2.4 其他操作
3. 演算法複雜度分析
3.1 入