二叉搜索树
特点:父节点比左边的大,比右边的小或者相等
包含中序,先序,后序遍历,插入,删除,搜索,前驱,后继等操作。
比较糟糕的情况下树高h = O(n)。
比较好的情况树高h = lgn。
插入,删除,搜索,最大值,最小值,前驱,后继,时间复杂度都是O(h)
遍历Θ(n)
任何基于比较的算法从n个元素的任意序列中构造一颗二叉搜索树,其最坏的情况下需要Ω(nlgn)。
特点:如果一颗二叉搜索树中的一个结点有两个孩子,那么它的后继没有左孩子,它的前驱没有右孩子。
前驱的特点:在树中比它小的最大元素。
后继的特点:在树中比它大的最小元素。
后继查找:该元素的若有右子树,那么是右子树的里的最小值,若没有右子树,那么是它最低祖先并且左孩子也是一个祖先。(即它最低祖先中那个有左孩子的祖先)因为只有有左孩子祖先才能比该元素大,否则该元素上面的祖先一直比该元素小。
三个遍历的特点:根据子树根的位置在左右子树的显示前中后来区别的。
中序:左-中-右
先序:中-左-右
后序:左-右-中
区别在于**中(子树根)**的位置
关于删除元素:
被删除的元素只有一个孩子的,删除该元素把它对应的孩子补上去,并且处理父结点关系
若有2个孩子的。
分两个情况:
一个是它的孩子刚好是它的后继,那么它孩子把它位置补上,并且安排好它原来的左孩子。
若它的孩子不是他的后继,那么它的后继要替代它的位置。先把后继的位置整理好,它的后继一定是没有左孩子的,所以它后继的右孩子替代它的后继位置,并安排好它后继的右孩子的父子关系,然后它后继替换它位置,并安排好它的左右孩子(它指代要被删的元素)
关于插入:
按照二叉树特点找一个空的位置即可。
#ifndef C11LEARN_BINARYSEARCHTREE_H
#define C11LEARN_BINARYSEARCHTREE_H
#include "../chapter10/BinaryTreeNode.h"
template<typename T>
class BinarySearchTree
{
protected:
BinaryTreeNode<T>* root;
int size;
public:
BinarySearchTree();
BinarySearchTree(const BinarySearchTree<T> & binarySearchTree);
BinarySearchTree<T> & operator= (const BinarySearchTree<T>& binarySearchTree);
virtual ~BinarySearchTree();
T minimum();
T maximum();
void insert(T key);
bool remove(const T& key);
bool contains(const T& key);
bool empty();
int length();
int successor(const T& key);
int predecessor(const T& key);
void inorder_tree_walk(void(*f)(const T& key));
void preorder_tree_walk(void(*f)(const T& key));
void postorder_tree_walk(void(*f)(const T& key));
BinaryTreeNode<T>* search(const T& key);
BinaryTreeNode<T>* successor(BinaryTreeNode<T>* node);
BinaryTreeNode<T>* predecessor(BinaryTreeNode<T>* node);
BinaryTreeNode<T>* get_root();
protected:
void transplant(BinaryTreeNode<T>*replaced,BinaryTreeNode<T>*substitute);
void insert(BinaryTreeNode<T>* node);
void remove(BinaryTreeNode<T>* node);
BinaryTreeNode<T>* minimum(BinaryTreeNode<T>* node);
BinaryTreeNode<T>* maximum(BinaryTreeNode<T>* node);
void iterative_inorder_tree_walk(void(*f)(BinaryTreeNode<T>* node));
void inorder_tree_walk(void(*f)(const T&key),BinaryTreeNode<T>* node);
void preorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node);
void postorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node);
void copy(BinaryTreeNode<T>* node);
};
template<typename T>
BinarySearchTree<T>::BinarySearchTree(){
root = nullptr;
size = 0;
}
template<typename T>
void BinarySearchTree<T>::copy(BinaryTreeNode<T>* node){
if(node!= nullptr)
{
insert(node->key);
if(node->left!= nullptr)
copy(node->left);
if(node->right!= nullptr)
copy(node->right);
}
}
template<typename T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T> & binarySearchTree){
root = nullptr;
copy(binarySearchTree.root);
}
template<typename T>
BinarySearchTree<T> & BinarySearchTree<T>::operator= (const BinarySearchTree<T>& binarySearchTree){
if(&binarySearchTree == this) return *this;
while (!empty())
remove(root);
root = nullptr;
copy(binarySearchTree.root);
return *this;
}
template<typename T>
BinarySearchTree<T>::~BinarySearchTree(){
while (!empty())
remove(root);
}
template<typename T>
void BinarySearchTree<T>::insert(const T key){
insert(new BinaryTreeNode<T>(key));
}
template<typename T>
bool BinarySearchTree<T>::remove(const T& key){
BinaryTreeNode<T>* current = search(key);
if(current == nullptr)
return false;
remove(current);
return true;
}
template<typename T>
bool BinarySearchTree<T>::contains(const T& key)
{
return search(key)!= nullptr;
}
template<typename T>
int BinarySearchTree<T>::successor(const T& key){
BinaryTreeNode<T>* current = successor(search(key));
if(current == nullptr) throw "overflow";
return current->key;
}
template<typename T>
int BinarySearchTree<T>::predecessor(const T& key){
BinaryTreeNode<T>* current = predecessor(search(key));
if(current == nullptr) throw "underflow";
return current->key;
}
template<typename T>
void BinarySearchTree<T>::insert(BinaryTreeNode<T>* node){
if(node == nullptr) return;
BinaryTreeNode<T> *prev = nullptr;
BinaryTreeNode<T>* current = root;
while (current!= nullptr)
{
prev = current;
if(node->key < current->key)
{
current = current->left;
}
else
{
current = current->right;
}
}
node->parent = prev;
if(prev == nullptr)
{
root = node;
}
else if(node->key<prev->key)
{
prev->left = node;
}
else
prev->right = node;
size++;
}
template<typename T>
void BinarySearchTree<T>::transplant(BinaryTreeNode<T>*replaced,BinaryTreeNode<T>*substitute){
if(replaced == nullptr) return;
if(replaced->parent == nullptr)
root = substitute;
else if(replaced->parent->right == replaced)
{
replaced->parent->right = substitute;
}
else{
replaced->parent->left = substitute;
}
if(substitute!= nullptr)
substitute->parent = replaced->parent;
}
template<typename T>
void BinarySearchTree<T>::remove(BinaryTreeNode<T>* node){
if(node == nullptr) return;
if(node->left == nullptr)
{
transplant(node,node->right);
}
else if(node->right == nullptr)
{
transplant(node,node->left);
}
else
{
BinaryTreeNode<T>* successor = minimum(node->right);
if(successor->parent != node)
{
transplant(successor,successor->right);
successor->right = node->right;
successor->right->parent = successor;
}
transplant(node,successor);
successor->left = node->left;
successor->left->parent = successor;
}
delete node;
size--;
}
template<typename T>
bool BinarySearchTree<T>::empty(){
return root == nullptr;
}
template<typename T>
int BinarySearchTree<T>::length() {
return size;
}
template<typename T>
T BinarySearchTree<T>::minimum(){
if(empty()) throw "underflow";
return minimum(root)->key;
}
template<typename T>
T BinarySearchTree<T>::maximum(){
if(empty()) throw "underflow";
return maximum(root)->key;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::minimum(BinaryTreeNode<T>* node){
if(node == nullptr) return node;
while (node->left!= nullptr)
node = node->left;
return node;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::maximum(BinaryTreeNode<T>* node){
if(node == nullptr) return node;
while (node->right!= nullptr)
node = node->right;
return node;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::search(const T& key){
BinaryTreeNode<T>* current = root;
while (current != nullptr && current->key != key)
{
if(key < current->key)
{
current = current->left;
}
else
{
current = current->right;
}
}
return current;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::successor(BinaryTreeNode<T>* node){
if(node == nullptr) return nullptr;
if(node->right!= nullptr)
{
return minimum(node->right);
}
BinaryTreeNode<T>* parent = node->parent;
while (parent!= nullptr && parent->right == node)
{
node = parent;
parent = parent->parent;
}
return parent;
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::predecessor(BinaryTreeNode<T>* node){
if(node == nullptr)return node;
if(node->left != nullptr)
return maximum(node->left);
BinaryTreeNode<T>* parent = node->parent;
while (parent!= nullptr && parent->left == node)
{
node = parent;
parent = parent->parent;
}
return parent;
}
template<typename T>
void BinarySearchTree<T>::inorder_tree_walk(void(*f)(const T& key)){
inorder_tree_walk(f,root);
}
template<typename T>
void BinarySearchTree<T>::iterative_inorder_tree_walk(void(*f)(BinaryTreeNode<T>* node)){
BinaryTreeNode<T>* prev = nullptr;
BinaryTreeNode<T>* current = root;
while (current!= nullptr)
{
if(current->parent == prev)
{
(*f)(current);
prev = current;
if(current->left!= nullptr)
{
current = current->left;
}
else if(current->right!= nullptr)
{
current = current->right;
}
else
{
current = current->parent;
}
}
else if(current->right!= nullptr && prev == current->left)
{
prev = current;
current = current->right;
}
else
{
prev = current;
current = current->parent;
}
}
}
template<typename T>
void BinarySearchTree<T>::preorder_tree_walk(void(*f)(const T& key)){
preorder_tree_walk(f,root);
}
template<typename T>
void BinarySearchTree<T>::postorder_tree_walk(void(*f)(const T& key)){
postorder_tree_walk(f,root);
}
template<typename T>
void BinarySearchTree<T>::inorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
if(node!= nullptr)
{
if(node->left!= nullptr)
inorder_tree_walk(f,node->left);
(*f)(node->key);
if(node->right!= nullptr)
inorder_tree_walk(f,node->right);
}
}
template<typename T>
void BinarySearchTree<T>::preorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
if(node!= nullptr)
{
(*f)(node->key);
if(node->left!= nullptr)
preorder_tree_walk(f,node->left);
if(node->right!= nullptr)
preorder_tree_walk(f,node->right);
}
}
template<typename T>
void BinarySearchTree<T>::postorder_tree_walk(void(*f)(const T& key),BinaryTreeNode<T>* node){
if(node!= nullptr)
{
if(node->left!= nullptr)
postorder_tree_walk(f,node->left);
if(node->right!= nullptr)
postorder_tree_walk(f,node->right);
(*f)(node->key);
}
}
template<typename T>
BinaryTreeNode<T>* BinarySearchTree<T>::get_root(){
return root;
}
#endif //C11LEARN_BINARYSEARCHTREE_H
测试代码
int arr[] = {15,6,18,3,7,17,20,2,4,13,9};
BinarySearchTree<int> binarySearchTree;
for (int i : arr) {
binarySearchTree.insert(i);
}
int min = binarySearchTree.minimum();
cout<<min<<endl;
int max = binarySearchTree.maximum();
cout<<max<<endl;
BinaryTreeNode<int> *node = binarySearchTree.search(9);
cout<<node->parent->key<<endl;
cout<<endl;
binarySearchTree.inorder_tree_walk([](const int & key){cout<<key<<" ";});
cout<<endl;
binarySearchTree.preorder_tree_walk([](const int & key){cout<<key<<" ";});
cout<<endl;
binarySearchTree.postorder_tree_walk([](const int & key){cout<<key<<" ";});
cout<<endl;
辅助类
BinaryTreeNode地址