1. 程式人生 > >二叉搜尋樹及判斷一棵樹是否平衡

二叉搜尋樹及判斷一棵樹是否平衡

二叉搜尋樹的特點:
1. 每個節點都有一個作為搜尋依據的關鍵碼(key),所有節點的關鍵碼互不相同。
2. 左子樹上所有節點的關鍵碼(key)都小於根節點的關鍵碼(key)。
3. 右子樹上所有節點的關鍵碼(key)都大於根節點的關鍵碼(key)。
4. 左右子樹都是二叉搜尋樹。
一棵二叉搜尋樹如下圖:
這裡寫圖片描述

平衡二叉樹的特點:
左右子樹的高度差<=1
無法達到絕對平衡是因為:如果一棵二叉樹只有兩個節點,則高度差永遠差1。

#pragma once
#include<iostream>
#include<stack>
using namespace std; template <class K, class V> struct BinarySearchTreeNode { K _key; V _value; BinarySearchTreeNode<K, V>* _left; BinarySearchTreeNode<K, V>* _right; BinarySearchTreeNode(K& k, V& v) :_key(k) , _value(v) , _left(NULL
) , _right(NULL) {} }; template <class K, class V> class BinarySearchTree { typedef BinarySearchTreeNode<K, V> Node; public: BinarySearchTree() : _root(NULL) {} bool Insert(K key, V val) { if (_root == NULL) { _root = new
Node(key, val); return true; } Node *cur = _root; Node *prev = NULL; //儲存cur的前一個節點 while (cur) { if (key < cur->_key) { prev = cur; cur = cur->_left; } else if (key > cur->_key) { prev = cur; cur = cur->_right; } else //已經存在 return false; } Node *node = new Node(key, val); if (key < prev->_key) prev->_left = node; else prev->_right = node; return true; } Node *Find(const K& key) { Node *cur = _root; while (cur) { if (key < cur->_key) cur = cur->_left; else if (key > cur->_key) cur = cur->_right; else //找到 return cur; } return NULL; } bool Remove(const K& key) { if (_root == NULL) return false; if (_root->_left == NULL && _root->_right == NULL) { delete _root; _root = NULL; return true; } Node *cur = _root; Node *parent = NULL; while (cur) { if (key < cur->_key) { parent = cur; cur = cur->_left; } else if (key > cur->_key) { parent = cur; cur = cur->_right; } else //找到要刪除的key { //1、cur的左孩子為空 if (cur->_left == NULL) { if (cur != _root) { if (parent->_left == cur) //判斷cur在parent的左邊還是右邊 parent->_left = cur->_right; else parent->_right = cur->_right; } else //刪除節點為跟節點並且左子樹為空 _root = cur->_right; } //2、cur的右孩子為空或左右都為空 else if (cur->_right == NULL) { if (cur != _root) { if (parent->_left == cur) //判斷cur在parent的左邊還是右邊 parent->_left = cur->_left; else parent->_right = cur->_left; } else _root = cur->_left; } //2、cur的左右都不為空 if (cur->_left != NULL && cur->_right != NULL) { Node *del = cur; //儲存要刪除的節點 parent = cur; cur = cur->_right; while (cur->_left) //找右子樹的最左節點 { parent = cur; cur = cur->_left; } // 將最左節點的值賦給要刪除的節點 del->_key = cur->_key; del->_value = cur->_value; if (cur == parent->_left) parent->_left = cur->_right; else parent->_right = cur->_right; } delete cur; cur = NULL; return true; } } return false; } bool Insert_R(K& key, V& val) { return _Insert_R(_root, key, val); } bool Find_R(const K& key) { return _Find_R(_root, key); } bool Remove_R(const K& key) { return _Remove_R(_root, key); } void Inorder() { _Inorder(_root); } bool Isbalance() { int depth = 0; return _Isbalance(_root,depth); } int Heigh() { return _Height(_root); } protected: //用後序遍歷的方式遍歷整課二叉樹,在遍歷到某一節點之後根據它左右節點的深度 //判斷當前節點是否平衡,再計算當前節點的深度。知道遍歷到根節點 bool _Isbalance(Node*& root, int& depth) { if (root == NULL) { depth = 0; return true; } int left = 0; int right = 0; if (_Isbalance(root->_left, left) && _Isbalance(root->_right, right)) { if (abs(left - right) <= 1) { depth = (left > right ? left + 1 : right + 1); return true; } } return false; } bool _Insert_R(Node *&root, K& key, V& val) { if (root == NULL) { root = new Node(key, val); return true; } if (key < root->_key) return _Insert_R(root->_left, key, val); else if (key > root->_key) return _Insert_R(root->_right, key, val); else return false; } bool _Find_R(Node *&root, const K& key) { if (root == NULL) return false; if (key < root->_key) return _Find_R(root->_left, key); else if (key > root->_key) return _Find_R(root->_right, key); else return true; } bool _Remove_R(Node *&root, const K& key) { if (root == NULL) return false; if (key < root->_key) return _Remove_R(root->_left, key); else if (key > root->_key) return _Remove_R(root->_right, key); else { Node *del = root; if (root->_left == NULL) root = root->_right;//利用遞迴的特點 else if (root->_right == NULL) root = root->_left; else { Node *parent = root; Node *cur = root; cur = cur->_right; while (cur->_left) { parent = cur; cur = cur->_left; } root->_key = cur->_key; root->_value = cur->_value; del = cur; if (parent->_left == cur) parent->_left = cur->_right; else parent->_right = cur->_right; } delete del; del = NULL; return true; } } int _Height(Node *&root) { if (root == NULL) return 0; int left = _Height(root->_left); int right = _Height(root->_right); return (left > right) ? left + 1 : right + 1; } //重複遍歷,低效 bool _Isbalance(Node*& root) { if (root == NULL) return true; int left = _Height(root->_left); int right = _Height(root->_right); if (abs(left - right) > 1) return false; return _Isbalance(root->_left) && _Isbalance(root->_right); } void _Inorder(Node* root) { //stack<Node*> s; //Node *cur = root; //while (cur || !s.empty()) //{ // while (cur) // { // s.push(cur); // cur = cur->_left; // } // if (!s.empty()) // { // Node* top = s.top(); // cout << top->_key << " "; // s.pop(); // cur = top->_right; // } //} //cout << endl; if (root == NULL) return; if (root) { _Inorder(root->_left); cout << root->_key << " "; _Inorder(root->_right); } } private: Node *_root; }; void Test1() { int a[] = { 4, 5, 6, 2, 1, 3 }; BinarySearchTree<int, int> bst; for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { bst.Insert_R(a[i], i); } bst.Inorder(); bst.Find_R(9); bst.Find_R(10); /*bst.Remove_R(1); bst.Inorder(); bst.Remove_R(7); bst.Inorder();*/ cout << "Isbalabce ? :" << bst.Isbalance() << endl; }