Chapter 11BinarySearchTree
来源:互联网 发布:海兴电力嵌入式软件 编辑:程序博客网 时间:2024/06/08 15:40
Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.
二叉搜索树(binary search tree)是一棵可能为空的二叉树,一棵非空的二叉搜索树满足以下特征:
1) 每个元素有一个唯一的关键值。
2) 根节点左子树的关键值(如果存在)小于根节点的关键值。
3) 根节点右子树的关键值(如果存在)大于根节点的关键值。
4) 根节点的左右子树也都是二叉搜索树。
带索引的二叉搜索树(indexed binary search tree)是普通的二叉搜索树在每个节点中添加一个 LeftSize域。这个域的值是该节点左子树的元素个数加1。图11 - 2是两棵带索引的二叉搜索树。节点里面的数字是元素的关键值,外面的是 LeftSize 的值。LeftSize同时给出了一个元素在子树中排名。例如,在图11-2a 的树中,根为20的子树中的元素(已排序)分别为 12,15,18,20,25和30,根节点的排名为4(即它在排序后的队列中是第 4个元素),在根为25的子树中的元素(已排序)为 25和30,因此25的排名为1且LeftSize的值也为1。
搜索
假设需要查找关键值为k的元素,那么先从根开始。如果根为空,查找失败;否则,将k与根的关键值相比较,如果k小于根节点的关键值,那么只要在左子树中搜索即可。如果k大于根节点的关键值,只需在右子树中搜索即可。如果k等于根节点的关键值,则查找成功,搜索终止。在子树中的查找与此类似。该过程的时间复杂性为 O (h),其中 h 是树的高度。
插入
若在二叉搜索树中插入一个新元素e,首先要验证e的关键值与树中已有元素的关键值是否相同,这可以通过用e的关键值对二叉树进行搜索来实现。如果搜索不成功,那么新元素将被插入到搜索的中断点。
例如,要将关键值为80的元素插入到图11-1b所示的树中去,首先对80进行搜索,由于搜索不成功而中断,最后检验的节点是关键值为40的节点,新元素将被插入到该节点之下作为其右孩子。插入后的结果如图11-3a 所示。图11-3b 给出了将关键值为35的元素插入到图11-3a 所示二叉树之后的结果。
删除
被删除元素的节点p的三种情况:1)p是树叶;2)p只有一个非空子树;3)p有两个非空子树。
P为 Solution
1.树叶 删除树叶节点
2.
只有一个非空子树 如果p是根节点,则将p删除,p的唯一子树的根节点成为新的根节点。
如果p有父节点parent,则修改parent的指针,使得parent 指向p的唯一孩子,然后删除节点p。
3.有两个非空子树 将p替换为它的左子树中的最大元素或右子树中的最小元素,从而转换到情况1或2.
1.p 是树叶:删除树叶节点。
要删除图11-3b所示树中的35,只要把其父节点的左孩子域置为零,然后删除该节点即可,删除后结果如图11-3a所示。要从树中删除80,只要把节点40的右孩子域置为零并删除节点80,其结果如图11-1b 所示。
2.p 只有一个非空子树:
如果p是根节点,则将p删除,p的唯一子树的根节点成为新的根节点。
如果p有父节点parent,则修改parent的指针,使得parent 指向p的唯一孩子,然后删除节点p。
例如,从图11-3b的树中删除关键值为5的元素,则修改该元素父节点的左孩子域,使其指向关键值为2的节点。
3.将p替换为它的左子树中的最大元素或右子树中的最小元素,从而转换到情况1或2.
假设删除图11-4a中关键值为40的元素,那么既可以用它左子树中的最大元素 (35),也可以用它右子树中的最小元素( 60)来替换它。如果选择右子树中的最小元素,那么把关键值为60的元素移到40被删除的位置,再把原来的叶节点60删除即可。结果如图 11-4b 所示。假定用左子树中的最大元素来代替被删除的元素40。左子树中的最大元素是35,且只有一个子女,把35移到40的节点中,将其左孩子指向原来节点35的唯一子女,结果如图11-4c 所示。
查找到左子树中的最大元素:首先移动到子树的根,然后沿着各节点的右孩子指针移动,直到右孩子指针为0为止。
查找右子树中的最小元素:首先移动到子树的根,然后沿着各节点的左孩子指针移动,直到左孩子指针为0为止。
删除一个有两个非空子树的节点时,该程序一般使用左子树的最大元素来进行替换,其复杂性为 O (h)。
高度
一棵n元素的二叉搜索树的高度可以与n一样大。例如,将一组关键值为[1, 2,3 , …,n]的元素按顺序插入到一棵空的二叉搜索树时,树的高度就会这样大。对树的搜索、插入和删除操作所需要的时间均为 O(n)。但是,当进行随机插入和删除操作时,二叉搜索树的平均高度是O(logn)。因此,每一个树操作的平均时间是O(logn)。
Review:
BinarySearchTree.h
Queue.h
Test.cc
BinarySearchTree.h
#ifndef BINARYSEARCHTREE_H_INCLUDED#define BINARYSEARCHTREE_H_INCLUDED#include "Queue.h"using std::cout;using std::cin;using std::endl;template<typename E, typename K>class BinarySearchTree;template<typename T>class Node{ template<typename E, typename K> class BinarySearchTree;public: Node(T data, Node<T> *left, Node<T> *right): data_(data), left_(left), right_(right) {} T data_; Node<T> *left_, *right_;};template<typename E, typename K>class BinarySearchTree{ template<E> friend void Output(Node<E> *root); // level-order traversal template<E> friend int Height(Node<E> *root); // get tree's heightpublic: BinarySearchTree(): root_(0) {} // default constructor ~BinarySearchTree(); // destructor void Initialization(); // create a binary search tree bool Search(const K &key) const; // search key in binary search tree bool Insert(const E &element); // insert element into binary search tree bool Delete(const K &key); // delete key's corresponding element Node<E> *root_;};template<typename E, typename K>BinarySearchTree<E, K>::~BinarySearchTree(){ delete root_; root_ = 0;}template<typename E, typename K>void BinarySearchTree<E, K>::Initialization(){ cout << "Please input your elements' amount:\n"; int amount; cin >> amount; cout << "Please input " << amount << " elements:\n"; for(int index = 0; index < amount; index++) { int element; cin >> element; Insert(element); }}template<typename E, typename K>bool BinarySearchTree<E, K>::Search(const K &key) const{ Node<E> *pointer = root_; while(pointer) { if(key < pointer->data_) // search in the sub-left-tree { pointer = pointer->left_; } else if(key == pointer->data_) // find { return true; } else // search in the sub-right-tree { pointer = pointer->right_; } } return false; // can't find}template<typename E, typename K>bool BinarySearchTree<E, K>::Insert(const E &element){ Node<E> *search_pointer = root_, *parent_pointer = 0; // check whether the element already exist in the binary search tree while(search_pointer) { // if the tree is not empty, then parent_pointer is the parent node of search_pointer parent_pointer = search_pointer; if(element < search_pointer->data_) // check in the sub-left-tree { search_pointer = search_pointer->left_; } else if(element > search_pointer->data_)// check in the right-left-tree { search_pointer = search_pointer->right_; } else { return false; // can't insert duplicate element into tree } } // insert element into tree Node<E> *new_node = new Node<E> (element, 0, 0); if(root_) { if(element < parent_pointer->data_) { parent_pointer->left_ = new_node; } else { parent_pointer->right_ = new_node; } } else { root_ = new_node; } return true;}template<typename E, typename K>bool BinarySearchTree<E, K>::Delete(const K &key){ // we assume delete_node->data_ = key, that is, we should delete delete_node // and if the tree is not empty: parent_node is the parent node of delete_node Node<E> *delete_node = root_, *parent_node = 0; while(delete_node && delete_node->data_ != key) { parent_node = delete_node; if(key < delete_node->data_) { delete_node = delete_node->left_; } else { delete_node = delete_node->right_; } } if(delete_node == 0) // key is not in the tree, so we can't delete it's element { return false; } // first we consider if the delete_node has two children and // convert this condition to the delete_node only has one child condition if(delete_node->left_ && delete_node->right_) { // left_max is the biggest node in the sub-left-tree of delete_node and // left_max_parent is the parent node of left_max Node<E> *left_max = delete_node->left_, *left_max_parent = delete_node; while(left_max->right_) // the rightmost node in sub-left-tree is the biggest node { left_max_parent = left_max; left_max = left_max->right_; } // transfer the condition: delete_node->data_ = left_max->data_; // assign left_max node's value to delete_node // update the nodes delete_node = left_max; parent_node = left_max_parent; } // up to now, the delete_node either has no child node or has only one child node // child_node is delete_node->left_ or delete_node->left_ or 0 Node<E> *child_node = (delete_node->left_) ? delete_node->left_ : delete_node->right_; if(delete_node == root_) // if delete_node is root, then update root to its' child_node { root_ = child_node; } // else update parent node's child to delete_node's child according delete_node's position else if(delete_node == parent_node->left_) { parent_node->left_ = child_node; } else if(delete_node == parent_node->right_) { parent_node->right_ = child_node; } delete delete_node; // free memory delete_node = 0; // and set it to zero return true;}template<typename E>void Output(Node<E> *root) // from top to bottom; from left to right{ if(root == 0) { cout << "Error: empty binary search tree!\n"; return; } cout << "BinarySearchTree contents in level order are:\n"; Queue<Node<E> *> queue; // use queue data structure queue.Push(root); Node<E> *node = queue.Top(); // get current top node of queue while(node) // while queue is not empty { cout << node->data_ << " "; // access node itself if(node->left_) { queue.Push(node->left_); // push left-sub-node into queue's rear } if(node->right_) { queue.Push(node->right_); // push right-sub-node into queue's rear } queue.Pop(); // delete the accessed node node = queue.Top(); // get the next node of queue } cout << endl;}template<typename E>int Height(Node<E> *root){ if(root) { int left = Height(root->left_); // get left-subtree's height int right = Height(root->right_); // get right-subtree's height return (left > right) ? ++left : ++right; // return max(left, right) + 1(root's height = 1) } return 0;}void AllOperation(){ BinarySearchTree<int, int> object; cout << "Please some numbers to execute the corresponding operation:\n"; cout << "0: exit.\n"; cout << "1: create a BinarySearchTree.\n"; cout << "2: search key in BinarySearchTree.\n"; cout << "3: insert element into BinarySearchTree.\n"; cout << "4: delete element from BinarySearchTree.\n"; cout << "5: get BinarySearchTree's height.\n"; cout << "6: print BinarySearchTree's contents.\n"; cout << "7: destroy BinarySearchTree.\n"; int operate; while(cin >> operate) { switch(operate) { case 0: goto END; case 1: object.Initialization(); Output(object.root_); break; case 2: cout << "Please input your key:\n"; int key; cin >> key; if(object.Search(key)) { cout << "Find Successfully!\n"; } else { cout << "Error: Can't Find!\n"; } break; case 3: cout << "Please input your element:\n"; int element; cin >> element; if(object.Insert(element)) { Output(object.root_); } else { cout << "Error: Elements in binary search tree can't be duplicate!\n"; } break; case 4: cout << "Please input your element:\n"; cin >> key; if(object.Delete(key)) { Output(object.root_); } else { cout << "Error: Can't find your key!\n"; } break; case 5: cout << "Binary search tree's height is " << Height(object.root_) << endl; break; case 6: Output(object.root_); break; case 7: object.~BinarySearchTree(); cout << "You have destroy the BinarySearchTree. " "Please establish BinarySearchTree before executing operations.\n"; break; default: cout << "Input Error! Please input again!\n"; break; } }END: ;}#endif // BINARYSEARCHTREE_H_INCLUDED
Queue.h
#ifndef QUEUE_H_INCLUDED#define QUEUE_H_INCLUDEDtemplate<typename T>class Queue;template<typename T>class QueueNode{ friend class Queue<T>;public: QueueNode(T data, QueueNode<T> *link): data_(data), link_(link) {}private: T data_; QueueNode<T> *link_;};template<typename T>class Queue{public: Queue(): first_(nullptr), last_(nullptr) {}; ~Queue() { QueueNode<T> *next; while(first_) { next = first_->link_; delete first_; first_ = next; } last_ = nullptr; } T Top() { if(first_) { return first_->data_; } return nullptr; } void Push(T data) { QueueNode<T> *new_node = new QueueNode<T> (data, nullptr); if(first_ == nullptr) { first_ = last_ = new_node; } else { last_->link_ = new_node; last_ = new_node; } } void Pop() { if(first_) { if(first_ == last_) { delete first_; first_ = last_ = nullptr; } else { QueueNode<T> *next = first_->link_; delete first_; first_ = next; } } }private: QueueNode<T> *first_, *last_;};#endif // QUEUE_H_INCLUDED
Test.cc
“`
include
include”BinarySearchTree.h”
using namespace std;
int main()
{
AllOperation();
return 0;
}
/*
1
8
5 11 8 20 6 15 10 9***5 11 8 20 6 10 15 9
5***5
3 1***5 1 11 8 20 6 10 15 9
3 30***5 1 11 8 20 6 10 15 30 9
2 9
2 1
2 100
3 30
4 1***5 11 8 20 6 10 15 30 9
4 6***5 11 8 20 10 15 30 9
4 5***11 8 20 10 15 30 9
5***4
4 8***11 10 20 9 15 30
5***3
4 11***10 9 20 15 30
4 10***9 20 15 30
5***3
6***9 20 15 30
7
2 8
4 4
5***0
6
1
5
1 2 3 4 5***1 2 3 4 5
5***5
0
*/
Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.
- Chapter 11BinarySearchTree
- BinarySearchTree
- BinarySearchTree
- BinarySearchTree
- BinarySearchTree
- 数据结构与算法分析 c++11 查找二叉树 BinarySearchTree
- Javascript-BinarySearchTree
- BinarySearchTree(BST)
- 算法导论示例-BinarySearchTree
- BinarySearchTree 二叉查找树
- [笔记] binarySearchTree AVLTree
- 二叉搜索树 BinarySearchTree
- 数据结构(java)----BinarySearchTree
- 搜索树BinarySearchTree
- Chapter 11 Exceptions
- !!!Chapter 11 Generic Algorithms
- Chapter 11 线程
- !!!Chapter 11 Amortized Analysis
- java 将对象写入文件
- <address>标签,为网页加入地址信息
- IOS Android 手机助手原理以及源码(Android 手机自动识别 二)
- OC动态字典和数组演示demo
- Ember.js 入门指南——控制器(controller)
- Chapter 11BinarySearchTree
- 枚举
- 图片延迟加载
- 插件推荐Echo.js 简单易用的图片延迟加载插件
- android性能优化----工具篇
- 51nod 1001 数组中和等于K的数对
- SlidingMenu开源框架简单使用
- js
- 10.14 python笔记