演算法導論第12章:二叉搜尋樹
阿新 • • 發佈:2019-01-04
基本性質
左子樹 < 根 < 右子樹
基本操作 O(logn)
1.查詢最大、最小關鍵字元素
根據二叉樹的基本性質,向左子樹或右子樹遞迴即可
2.查詢前驅和後繼
查詢結點X的後繼Y分為兩種情況:
①右結點存在,即只需要找到右子樹中最小的元素就好了
②右結點不存在,此時就要向親代查詢,直到找到右上方的親代,此時Y是X的最底層祖先,且Y的左孩子是X的一個祖先。
3.插入
迭代演算法:類似於一根小棒在樹中移動,最終把待插入元素放置在一個空結點上
4.刪除
假設要刪除結點Z,那麼需要分3種情況討論:
①若沒有孩子,直接刪除即可,以空結點NULL代替之。
②若只有一個孩子,以孩子代替結點Z
③若有兩個孩子
a)若右孩子為其後繼:將右子樹代替結點Z即可
b)若右孩子不是其後繼:設Z的後繼為Y,Y的右孩子為X,則將Y原來的位置以X代替,Y將Z代替
利用二叉樹進行排序 Ω(n*logn)
不斷地插入節點,最後中序遍歷即可——元素之間的比較和快速排序相同,故它們的執行效率相似。若採用隨機化策略,則平均執行時間為θ(n*logn),樹高為θ(logn)
二叉搜尋樹類的實現(C++)
#include <iostream> using namespace std; #pragma once //設想是:當樹為空時,root一定為nullptr struct node { int element = 0; node* parent = nullptr; node* left = nullptr; node* right = nullptr; }; class BinarySearchTree { public: BinarySearchTree() {} ~BinarySearchTree(); int size(); int maximum(); int minimum(); void print(); void clear(); void insert(const int&); void remove(const int&); private: int cnt = 0; node* root = nullptr; node* minimum(node* x); void transplant(node* u, node* v); void clear(node*); void print(node*); }; void BinarySearchTree::clear(node* x) { if(x == nullptr) return; if(x->left != nullptr) clear(x->left); if(x->right != nullptr) clear(x->right); delete x; x = nullptr; } void BinarySearchTree::clear() { cnt = 0; clear(root); } BinarySearchTree::~BinarySearchTree() { clear(root); } int BinarySearchTree::maximum() { node* x = root; if(x == nullptr) return 0; while(x->right != nullptr) x = x->right; return x->element; } node* BinarySearchTree::minimum(node* x) { if(x == nullptr) return 0; while(x->left != nullptr) x = x->left; return x; } int BinarySearchTree::minimum() { return minimum(root)->element; } int BinarySearchTree::size() { return cnt; } void BinarySearchTree::print(node* x) { if(x == nullptr) return; if(x->left != nullptr) print(x->left); cout << x->element << ' '; if(x->right != nullptr) print(x->right); } void BinarySearchTree::print() { print(root); cout<<'\n'; } void BinarySearchTree::insert(const int& a) { if(cnt == 0) { root = new node; root->element = a; } else { node* x = root; node* y = nullptr; while(x != nullptr) { y = x; if(a > x->element) x = x->right; else x = x->left; } node* t = new node; t->parent = y; t->element = a; if(a > y->element) y->right = t; else y->left = t; } ++cnt; } void BinarySearchTree::transplant(node* u, node* v) { if(u->parent == nullptr) root = v; else if(u == u->parent->left) u->parent->left = v; else u->parent->right = v; if(v != nullptr) v->parent = u->parent; } void BinarySearchTree::remove(const int& a) { node* x = root; while(x != nullptr && x->element != a) { if(a > x->element) x = x->right; else x = x->left; } if(x == nullptr) return; --cnt; if(x->left == nullptr) transplant(x, x->right); else if(x->right == nullptr) transplant(x, x->left); else { node* y = minimum(x->right); if(y->parent != x) { transplant(y, y->right); y->right = x->right; y->right->parent = y; } transplant(x, y); y->left = x->left; y->left->parent = y; } }