1. 程式人生 > >資料結構實現 10.2:對映_基於AVL樹實現(C++版)

資料結構實現 10.2:對映_基於AVL樹實現(C++版)

資料結構實現 10.2:對映_基於AVL樹實現(C++版)

1. 概念及基本框架

對映 是一種高階資料結構,其實現方法也不唯一,但儲存上使用 鏈式儲存(即記憶體的物理空間是不連續的)。這一節我們通過 AVL樹

來實現對映這種資料結構。

對映

對映 的基本特性:
1.對映內元素包含 鍵(key)值(value) ,而且一一對應。
2.對映內的元素的鍵 不能重複
注:有些對映(多重對映)中元素的鍵也可以重複。
顯然,AVL樹滿足對映的特性,所以我們嘗試利用AVL樹來實現對映。
首先,我們可以利用一個由 純虛擬函式 構成的 抽象類 作為一個介面來定義這些操作。具體程式碼如下:

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 AVLTreeMap : public Map<
K, V>{ ... private: AVLTree<K, V> avl; };

這裡為了避免重複設計就可以相容更多資料型別,引入了 泛型 ,即 模板 的概念。(模板的關鍵字是 classtypename
這裡的 avl 表示一棵 AVL樹 ,同樣,為了保護資料,變數設定為 private
注:這裡沒有顯式的給出建構函式,因為子類中除了AVL樹物件之外沒有特別需要初始化的東西。編譯器會預設先呼叫 AVL樹 類(即父類)的建構函式,再去呼叫 對映 類(即子類)的建構函式。
實現了前面的程式之後,接下來就是一個對映的增、刪、改、查以及一些其他基本操作,接下來利用程式碼去實現。

2. 基本操作程式實現

2.1 增加操作

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	...
	//增加操作
	void add(K key, V value){
		avl.add(key, value);
	}
	...
};

直接呼叫AVL樹的增加操作。(因為AVL樹中的元素本來就不重複)

2.2 刪除操作

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	...
	//刪除操作
	V remove(K key){
		V res = avl.get(key);
		avl.remove(key);
		return res;
	}
	...
};

直接呼叫AVL樹的刪除操作。

2.3 修改操作

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	...
	//修改操作
	void set(K key, V value){
		avl.add(key, value);
	}
	...
};

2.4 查詢操作

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	...
	//查詢操作
	bool contains(K key){
		return avl.contains(key);
	}
	V get(K key){
		return avl.get(key);
	}
	...
};

2.5 其他操作

對映還有一些其他的操作,包括 對映大小 的查詢等操作。

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	int size(){
		return avl.size();
	}
	bool isEmpty(){
		return avl.isEmpty();
	}
	...
};

3. 演算法複雜度分析

因為對映操作直接呼叫了AVL樹的操作,所以其操作的時間複雜度和AVL樹相同。

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)

很顯然,利用AVL樹很容易實現對映這一高階資料結構。

4. 完整程式碼

程式完整程式碼(這裡使用了標頭檔案的形式來實現類)如下。
這裡不再給出AVL樹的實現,如有需要,可參看 10.1

抽象類 介面程式碼:

#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 contains(K key) = 0;
	virtual V get(K key) = 0;
};

#endif

對映類 程式碼:

#ifndef __AVLTREEMAP_H__
#define __AVLTREEMAP_H__

#include "Map.h"
#include "AVLTree.h"

template <class K, class V>
class AVLTreeMap : public Map<K, V>{
public:
	int size(){
		return avl.size();
	}
	bool isEmpty(){
		return avl.isEmpty();
	}
	//增加操作
	void add(K key, V value){
		avl.add(key, value);
	}
	//刪除操作
	V remove(K key){
		V res = avl.get(key);
		avl.remove(key);
		return res;
	}
	//修改操作
	void set(K key, V value){
		avl.add(key, value);
	}
	//查詢操作
	bool contains(K key){
		return avl.contains(key);
	}
	V get(K key){
		return avl.get(key);
	}
private:
	AVLTree<K, V> avl;
};

#endif