好久不見,我是云邊有個稻草人,偶爾中二博主與你分享C++領域專業知識^(* ̄(oo) ̄)^
《C++》—本篇文章所屬專欄—持續更新中—歡迎訂閱~喔
目錄
一、AVL的概念
二、AVL樹的實現
2.1 AVL樹的結構
2.2?AVL樹的插入
【AVL樹插入?個值的大概過程】
【平衡因?更新】
【插?結點及更新平衡因?的代碼實現】?
2.3 旋轉
【旋轉的原則】
【右單旋+兩個坑+代碼實現】
【左單旋+代碼實現】
【左右雙旋+代碼實現】
【右左雙旋+代碼實現】
2.4?AVL樹的查找
2.5?AVL樹平衡檢測
2.6?AVL樹的刪除
三、完整代碼
AVLTree.h
test.cpp?
正文開始——
一、AVL的概念
- AVL樹是最先發明的?平衡?叉查找樹,AVL是?顆空樹,或者具備下列性質的?叉搜索樹:它的 左右?樹都是AVL樹,且左右?樹的?度差的絕對值不超過1。AVL樹是?顆高度平衡搜索?叉樹, 通過控制高度差去控制平衡。
- AVL樹得名于它的發明者G. M. Adelson-Velsky和E. M. Landis是兩個前蘇聯的科學家,他們在1962 年的論文《An algorithm for the organization of information》中發表了它。
- AVL樹實現這?我們引??個平衡因?(balance factor)的概念,每個結點都有?個平衡因?,任何結點的平衡因?等于右?樹的?度減去左?樹的?度,也就是說任何結點的平衡因?等于0/1/-1, AVL樹并不是必須要平衡因?,但是有了平衡因?可以更?便我們去進?觀察和控制樹是否平衡, 就像?個風向標?樣。
- 思考?下為什么AVL樹是?度平衡搜索?叉樹,要求?度差不超過1,?不是?度差是0呢?0不是更好的平衡嗎?畫畫圖分析我們發現,不是不想這樣設計,?是有些情況是做不到?度差是0的。?如?棵樹是2個結點,4個結點等情況下,?度差最好就是1,?法做到?度差是0
- AVL樹整體結點數量和分布和完全?叉樹類似,?度可以控制在logN,那么增刪查改的效率也可 以控制在O(logN) ,相??叉搜索樹有了本質的提升
二、AVL樹的實現
2.1 AVL樹的結構
template<class K,class V>
struct AVLTreeNode
{//相比于二叉搜索樹多了parent和平衡因子pair<K, V> _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf;//balance factorAVLTreeNode(const pair<K, V> pair):_kv(pair),_left(nullptr),_right(nullptr),_parent(nullptr)_bf(0){ }
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public://......
private:Node* _root = nullptr;
};
2.2?AVL樹的插入
【AVL樹插入?個值的大概過程】
- 插入?個值按?叉搜索樹規則進行插?。
- 新增結點以后,只會影響祖先結點的?度,也就是可能會影響部分祖先結點的平衡因?,所以更新 從新增結點->根結點路徑上的平衡因?,實際中最壞情況下要更新到根,有些情況更新到中間就可 以停?了,具體情況我們下?再詳細分析。
- 更新平衡因?過程中沒有出現問題,則插?結束
- 更新平衡因?過程中出現不平衡,對不平衡?樹旋轉,旋轉后本質調平衡的同時,本質降低了?樹的?度,不會再影響上?層,所以插?結束。
【平衡因?更新】
更新原則:
- 平衡因? = 右?樹?度-左?樹?度
- 只有?樹?度變化才會影響當前結點平衡因?。
- 插?結點,會增加?度,所以新增結點在parent的右?樹,parent的平衡因?++,新增結點在 parent的左?樹,parent平衡因?--
- parent所在?樹的?度是否變化決定了是否會繼續往上更新
更新停?條件:
- 更新后parent的平衡因?等于0,更新中parent的平衡因?變化為-1->0 或者 1->0,說明更新前 parent?樹?邊??邊低,新增的結點插?在低的那邊,插?后parent所在的?樹?度不變,不會影響parent的?親結點的平衡因?,更新結束。
- 更新后parent的平衡因?等于1 或 -1,更新前更新中parent的平衡因?變化為0->1 或者 0->-1,說 明更新前parent?樹兩邊?樣?,新增的插?結點后,parent所在的?樹?邊??邊低,parent所 在的?樹符合平衡要求,但是?度增加了1,會影響parent的?親結點的平衡因?,所以要繼續向 上更新。
- 更新后parent的平衡因?等于2 或 -2,更新前更新中parent的平衡因?變化為1->2 或者 -1->-2,說 明更新前parent?樹?邊??邊低,新增的插?結點在?的那邊,parent所在的?樹?的那邊更高了,破壞了平衡,parent所在的?樹不符合平衡要求,需要旋轉處理,旋轉的?標有兩個:1、把 parent子樹旋轉平衡。2、降低parent?樹的?度,恢復到插?結點以前的?度。所以旋轉后也不 需要繼續往上更新,插?結束。
- 不斷更新,更新到根,跟的平衡因子是1或-1也停止了。
根據上面的更新規則和更新停止的條件思考一下下面的實際場景:
【插?結點及更新平衡因?的代碼實現】?
bool Insert(const pair<K,V>& kv)
{// 1.找到空位置插入新結點if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if(cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;// 2.更新平衡因子while (parent){if (cur == parent->_left){parent->_bf--;}else if (cur == parent->_right){parent->_bf++;}if (parent->_bf == 0){break;}else if (parent->_bf == -1 || parent->_bf == 1){//繼續向上更新cur = parent;parent = parent->_parent;}else if (parent->_bf == -2 || parent->_bf == 2){//旋轉break;}else{assert(false);}}return true;
}
2.3 旋轉
【旋轉的原則】
- 保持搜索樹的規則
- 讓旋轉的樹從不滿足變平衡,其次降低旋轉樹的高度旋轉總共分為四種,左單旋/右單旋/左右雙旋/右左雙旋。 說明:下面的圖中,有些結點我們給的是具體值,如10和5等結點,這?是為了方便講解,實際中是什么值都可以,只要大小關系符合搜索樹的性質即可。
【右單旋+兩個坑+代碼實現】
- 本圖1展?的是10為根的樹,有a/b/c抽象為三棵高度為h的子樹(h>=0),a/b/c均符合AVL樹的要求。10可能是整棵樹的根,也可能是?個整棵樹中局部的?樹的根。這?a/b/c是?度為h的?樹,是?種概括抽象表示,他代表了所有右單旋的場景,實際右單旋形態有很多種,具體圖2/圖3/圖4/ 圖5進?了詳細描述。
- 在a?樹中插??個新結點,導致a?樹的?度從h變成h+1,不斷向上更新平衡因?,導致10的平衡因?從-1變成-2,10為根的樹左右?度差超過1,違反平衡規則。10為根的樹左邊太?了,需要往右邊旋轉,控制兩棵樹的平衡。
- 旋轉核?步驟,因為5 < b?樹的值 < 10,將b變成10的左?樹,10變成5的右?樹,5變成這棵樹新 的根,符合搜索樹的規則,控制了平衡,同時這棵的?度恢復到了插?之前的h+2,符合旋轉原則。如果插?之前10整棵樹的?個局部?樹,旋轉后不會再影響上?層,插?結束了。
形象的描述
看著下面的圖一,左邊高,那就想象著把10節點往右邊按下去,把b作為10的左子樹,10一整棵作為5的右子樹,5作為一整棵樹的根節點,完美~
兩個坑:
代碼實現:
先把上面的旋轉過程想清楚,再思考遇到的兩個坑,下面的右單旋代碼就不難實現。
節點相互指來指去可能會比較繞,要自己靜下心來好好想清楚,按照心里思考之后正確的順序去改變指向。也就是改變了四個指向
void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;//subLR可能為空,也就是h高度為0時if (subLR)subLR->_parent = parent;//保存這里根節點的parentNode* ppNode = parent->_parent;parent->_parent = subL;subL->_right = parent;//有兩種判斷是否是根節點的方法//if(ppNode == nullptr)if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}subL->_bf = 0;parent->_bf = 0;
}
【左單旋+代碼實現】
- 本圖展?的是10為根的樹,有a/b/c抽象為三棵?度為h的?樹(h>=0),a/b/c均符合AVL樹的要 求。10可能是整棵樹的根,也可能是?個整棵樹中局部的?樹的根。這?a/b/c是?度為h的?樹, 是?種概括抽象表?,他代表了所有右單旋的場景,實際右單旋形態有很多種,具體跟上?左旋類 似。
- 在a?樹中插??個新結點,導致a?樹的?度從h變成h+1,不斷向上更新平衡因?,導致10的平 衡因?從1變成2,10為根的樹左右?度差超過1,違反平衡規則。10為根的樹右邊太?了,需要往 左邊旋轉,控制兩棵樹的平衡。
- 旋轉核?步驟,因為10 < b?樹的值 < 15,將b變成10的右?樹,10變成15的左?樹,15變成這棵 樹新的根,符合搜索樹的規則,控制了平衡,同時這棵的?度恢復到了插?之前的h+2,符合旋轉 原則。如果插?之前10整棵樹的?個局部?樹,旋轉后不會再影響上?層,插?結束了。
代碼實現:
會了上面的右單旋的兩個坑和代碼的實現,這里的左單旋一樣的過程,也是小case啦,嘗試自己寫一下
void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;subR->_left = parent;Node* ppNode = parent->_parent;parent->_parent = subR;if (ppNode == nullptr){_root = subR;subR->_parent = nullptr;}else{subR->parent = ppNode;if (parent == ppNode->_left){ppNode->_left = subR;}else{ppNode->_right = subR;}}subR->_bf = parent->_bf = 0;
}
看了上面的圖發現,右單旋或者左單旋都是純粹的左邊高或者右邊高,那如果不是純粹的左邊高或者右邊高該怎么辦?雙旋!
【左右雙旋+代碼實現】
通過圖7和圖8可以看到,左邊?時,如果插?位置不是在a?樹,?是插?在b?樹,b?樹?度從h變 成h+1,引發旋轉,右單旋?法解決問題,右單旋后,我們的樹依舊不平衡。右單旋解決的純粹的左邊?,但是插?在b?樹中,10為跟的?樹不再是單純的左邊?,對于10是左邊?,但是對于5是右邊高,需要?兩次旋轉才能解決,以5為旋轉點進??個左單旋,以10為旋轉點進??個右單旋,這棵樹 這棵樹就平衡了。
(默默地吐槽一句,qq的長截圖是咋回事的嘛,老是拼接中斷。回答我,look my eyes!)
(回到正題)?
- 圖7和圖8分別為左右雙旋中h==0和h==1具體場景分析,下?我們將a/b/c?樹抽象為?度h的AVL?樹進?分析,另外我們需要把b?樹的細節進?步展開為8和左?樹?度為h-1的e和f?樹,因為 我們要對b的?親5為旋轉點進?左單旋,左單旋需要動b樹中的左?樹。b?樹中新增結點的位置 不同,平衡因?更新的細節也不同,通過觀察8的平衡因?不同,這?我們要分三個場景討論。
- 場景1:h >= 1時,新增結點插?在e?樹,e?樹?度從h-1并為h并不斷更新8->5->10平衡因?,引發旋轉,其中8的平衡因?為-1,旋轉后8和5平衡因?為0,10平衡因?為1。
- 場景2:h >= 1時,新增結點插?在f?樹,f?樹?度從h-1變為h并不斷更新8->5->10平衡因?,引發旋轉,其中8的平衡因?為1,旋轉后8和10平衡因?為0,5平衡因?為-1。
- 場景3:h == 0時,a/b/c都是空樹,b??就是?個新增結點,不斷更新5->10平衡因?,引發旋 轉,其中8的平衡因?為0,旋轉后8和10和5平衡因?均為0。
代碼實現:
void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;//先進行左單旋RotateL(subL);//再進行右單旋RotateR(parent);//根據bf分情況來更新平衡因子if (bf == -1){subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if (bf == 1){subL->_bf = -1;parent->_bf = 0;subLR->_bf = 0;}else if (bf == 0){subL->_bf = 0;parent->_bf = 0;subLR->_bf = 0;}else{assert(false);}
}
【右左雙旋+代碼實現】
- 跟左右雙旋類似,下?我們將a/b/c?樹抽象為?度h的AVL?樹進?分析,另外我們需要把b?樹的 細節進?步展開為12和左?樹?度為h-1的e和f?樹,因為我們要對b的?親15為旋轉點進?右單 旋,右單旋需要動b樹中的右?樹。b?樹中新增結點的位置不同,平衡因?更新的細節也不同,通 過觀察12的平衡因?不同,這?我們要分三個場景討論。
- 場景1:h >= 1時,新增結點插?在e?樹,e?樹?度從h-1變為h并不斷更新12->15->10平衡因 ?,引發旋轉,其中12的平衡因?為-1,旋轉后10和12平衡因?為0,15平衡因?為1。
- 場景2:h >= 1時,新增結點插?在f?樹,f?樹?度從h-1變為h并不斷更新12->15->10平衡因?, 引發旋轉,其中12的平衡因?為1,旋轉后15和12平衡因?為0,10平衡因?為-1。
- 場景3:h == 0時,a/b/c都是空樹,b??就是?個新增結點,不斷更新15->10平衡因?,引發旋 轉,其中12的平衡因?為0,旋轉后10和12和15平衡因?均為0。
代碼實現:
void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;//先進行右單旋RotateR(subR);//再進行左單旋RotateL(parent);//更新平衡因子if (bf == -1){subRL->_bf = 0;subR->_bf = 1;parent->_bf = 0;}else if (bf == 1){subRL->_bf = 0;subR->_bf = 0;parent->_bf = -1;}else if(bf == 0){subRL->_bf = 0;subR->_bf = 0;parent->_bf = 0;}else{assert(false);}}
2.4?AVL樹的查找
那?叉搜索樹邏輯實現即可,搜索效率為 O(logN)
//AVL樹的查找Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}
2.5?AVL樹平衡檢測
怎么去檢測AVL樹是否合格呢?檢查每個結點的平衡因子?那如果每個結點里面存儲的平衡因子本身就是錯的怎么辦?所以這種辦法不可行
判斷實現的AVL樹是否合格,可以通過檢查左右?樹?度差的程序進?反向驗證,同時檢查?下結點的平衡因?更新是否出現了問題。
int _Height(Node* root)
{if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}bool _IsBalanceTree(Node* root)
{// 空樹也是AVL樹if (nullptr == root)return true;// 計算pRoot結點的平衡因?:即pRoot左右?樹的?度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果計算出的平衡因?與pRoot的平衡因?不相等,或者// pRoot平衡因?的絕對值超過1,則?定不是AVL樹if (abs(diff) >= 2){cout << root->_kv.first << "?度差異常" << endl;return false;}if (root->_bf != diff){cout << root->_kv.first << "平衡因?異常" << endl;return false;}// pRoot的左和右如果都是AVL樹,則該樹?定是AVL樹return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
}// 測試代碼
void TestAVLTree1()
{AVLTree<int, int> t;// 常規的測試?例//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的帶有雙旋場景的測試?例int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){t.Insert({ e, e });}t.InOrder();cout << t.IsBalanceTree() << endl;
}// 插??堆隨機值,測試平衡,順便測試?下?度和性能等
void TestAVLTree2()
{const int N = 100000;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(rand() + i);}size_t begin2 = clock();AVLTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));}size_t end2 = clock();cout << "Insert:" << end2 - begin2 << endl;cout << t.IsBalanceTree() << endl;cout << "Height:" << t.Height() << endl;cout << "Size:" << t.Size() << endl;size_t begin1 = clock();// 確定在的值/*for (auto e : v){t.Find(e);}*/// 隨機值for (size_t i = 0; i < N; i++){t.Find((rand() + i));}size_t end1 = clock();cout << "Find:" << end1 - begin1 << endl;
}
2.6?AVL樹的刪除
AVL樹的刪除本章節不做講解,有興趣的同學可參考:《殷?昆 數據結構:??向對象?法與C++語 ?描述》中講解。
三、完整代碼
AVLTree.h
#pragma once
#include<iostream>
#include<assert.h>
#include<vector>using namespace std;template<class K, class V>
struct AVLTreeNode
{// 需要parent指針,后續更新平衡因子可以看到pair<K, V> _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf; // balance factorAVLTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _bf(0){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;// 更新平衡因子while (parent){if (cur == parent->_right){parent->_bf++;}else{parent->_bf--;}if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){// 旋轉if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);}else if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);}else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);}else{assert(false);}break;}else{assert(false);}}return true;}void InOrder(){_InOrder(_root);cout << endl;}bool IsBalanceTree(){return _IsBalanceTree(_root);}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}int Height(){return _Height(_root);}int Size(){return _Size(_root);}
private:int _Size(Node* root){if (root == nullptr)return 0;return _Size(root->_left) + _Size(root->_right) + 1;}bool _IsBalanceTree(Node* root){// 空樹也是AVL樹if (nullptr == root)return true;// 計算pRoot結點的平衡因子:即pRoot左右子樹的高度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果計算出的平衡因子與pRoot的平衡因子不相等,或者// pRoot平衡因子的絕對值超過1,則一定不是AVL樹if (abs(diff) >= 2){cout << root->_kv.first << "高度差異常" << endl;return false;}if (root->_bf != diff){cout << root->_kv.first << "平衡因子異常" << endl;return false;}// pRoot的左和右如果都是AVL樹,則該樹一定是AVL樹return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);}int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;//if (ppNode == nullptr)if (parent == _root){_root = subL;subL->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}parent->_bf = 0;subL->_bf = 0;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (parentParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subR;}else{parentParent->_right = subR;}subR->_parent = parentParent;}parent->_bf = subR->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1){subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if (bf == 1){subL->_bf = -1;parent->_bf = 0;subLR->_bf = 0;}else if (bf == 0){subL->_bf = 0;parent->_bf = 0;subLR->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;}else if (bf == 1){subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;}else{assert(false);}}
private:Node* _root = nullptr;
};// 測試代碼
void TestAVLTree1()
{AVLTree<int, int> t;// 常規的測試用例//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的帶有雙旋場景的測試用例int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){//這里是一個調試打斷點的技巧(類似于條件斷點,斷點不能打在空語句,寫一句無關緊要的代碼停一下即可)/*if (e == 14){int x = 0;}*/t.Insert({ e, e });cout << "Insert:" << e << "->";cout << t.IsBalanceTree() << endl;}t.InOrder();cout << t.IsBalanceTree() << endl;
}// 插入一堆隨機值,測試平衡,順便測試一下高度和性能等
void TestAVLTree2()
{const int N = 1000000;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; i++){v.push_back(rand() + i);}size_t begin2 = clock();AVLTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));}size_t end2 = clock();cout << t.IsBalanceTree() << endl;cout << "Insert:" << end2 - begin2 << endl;cout << "Height:" << t.Height() << endl;cout << "Size:" << t.Size() << endl;size_t begin1 = clock();// 確定在的值/*for (auto e : v){t.Find(e);}*/// 隨機值for (size_t i = 0; i < N; i++){t.Find((rand() + i));}size_t end1 = clock();cout << "Find:" << end1 - begin1 << endl;
}
test.cpp?
#include"AVLTree.h"int main()
{//TestAVLTree1();TestAVLTree2();return 0;
}
跟著文章把知識和代碼邏輯順一遍
博主也是懶,斷斷續續終于寫完了......
看看今天能不能繼續更(對了,要是忽然想到尷尬的事情,死去的回憶開始攻擊我怎么辦,尷尬的原地攥緊兩個拳頭開始齜牙咧嘴)
完——
Call You Tonight
至此結束——
我是云邊有個稻草人
期待與你的下一次相遇......