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.

0 0
原创粉丝点击