算法导论 二叉查找树

在二叉查找树进行基本操作的时间与树的高度成正比。

二叉查找树基本性质:

设x为树中某个结点。如果y是x的左子树中的一个结点,则key[y] <= key[x]。如果y是x的右子树中的一个结点,则key[x] <= key[y]。也就是说,某个结点x的左子树中的结点元素必定不大于其右子树中的结点元素。

二叉查找树基本操作:

1.在二叉查找树中查找某个给定的key,有递归和非递归的版本。

递归:根据二叉查找树的性质,在某个结点左子树或右子树中递归查找,直到找到叶子结点

迭代:从根结点开始迭代,根据二叉查找树性质,在左子树或右子树中查找,直到叶子结点

2.获得树中最小元素,根据二叉查找树性质,最小元素一定在整个树的最左边。

3.获得树种最大元素,根据二叉查找树性质,最大元素一定在整个树的最右边。

4.前驱和后继,有时候要给出某个结点在中序遍历树时候的前驱或后继。

后继:某一结点x的后继即具有大于key[x]的关键字中最小的那个。如果结点x右子树不为空,则结点x的后继为其右子树中最小元素。如果结点x右子树为空,假设其后继为y,则y是x的最低祖先结点,且y的左儿子也是x的祖先。

前驱:根据上述后继的分析可以得到前驱相关性质。

5.插入,与查找关键字key时过程相仿,将key插入到合适位置,但要注意当树为空时候的插入情况。

6删除。与插入相比较为复杂,分为3种情况,假设要删除结点为x

(1)当x左右孩子均为空的时候,也就是结点x为叶结点的时候,直接删除x

(2)当x左右孩子中仅有一个为空的时候,设这个结点为y,则将y设为x父结点的孩子,然后将x删除。

(3)当x左右孩子都不为空的时候,找到x的后继y,再用y替换x的内容,y孩子结点z设为其父节点的孩子,并将y删除。


具体二叉查找树代码:

#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H

#include <iostream>

template<typename T>
struct Node
{
    T key;
    Node *P;
    Node *L; 
    Node *R; 

    Node(T data = T(),Node<T> *P = NULL,Node<T> *L = NULL,Node<T> *R = NULL)
    {   
        this->key = data;
        this->P = P;
        this->L = L;
        this->R = R;
    }   
};

template<typename T>
class Binary_Search_Tree
{
public:
    Binary_Search_Tree();
    ~Binary_Search_Tree();

    typedef Node<T>     Tree_Node;

    Tree_Node* Insert(const T& data);
    Tree_Node* Find(const T& data);
    void Delete(const T& data);
    Tree_Node* FindMax();
    Tree_Node* FindMin();

    void Display();
private:
    void free_node(Tree_Node *p);

    Tree_Node* tree_search(Tree_Node *x,const T& data);
    Tree_Node* iterative_tree_search(Tree_Node *x,const T& data);
    Tree_Node* tree_minimum(Tree_Node *root);
    Tree_Node* tree_maximum(Tree_Node *root);
    Tree_Node* tree_successor(Tree_Node *x);
    Tree_Node* tree_predecessor(Tree_Node *x);
    Tree_Node* tree_delete(Tree_Node *p);
    Tree_Node* tree_insert(Tree_Node *p);

    void Display(const Tree_Node *p);

    Tree_Node* m_pRoot;
#ifdef _DEBUG
    int cnt;
#endif
};

template<typename T>
Binary_Search_Tree<T>::Binary_Search_Tree() : m_pRoot(NULL)
{
#ifdef _DEBUG
    cnt = 0;
#endif
}

template<typename T>
Binary_Search_Tree<T>::~Binary_Search_Tree()
{
    free_node(m_pRoot);
#ifdef _DEBUG
    std::cout << "after new and free endtime the cnt is" << cnt << std::endl;
#endif
}

template<typename T>
void Binary_Search_Tree<T>::Display()
{
    Display(m_pRoot);
}

template<typename T>
void Binary_Search_Tree<T>::Display(const Tree_Node* p)
{
    if(p == NULL)
        return ;

    Display(p->L);

    std::cout << "Node = " << p->key << std::endl;

    Display(p->R);
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::Insert(const T& data)
{
    Tree_Node *z = new Tree_Node(data);
#ifdef _DEBUG
    ++cnt;
#endif
    return  tree_insert(z);
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::Find(const T& data)
{
    return iterative_tree_search(m_pRoot,data);
}
template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::FindMax()
{
    return tree_maximum(m_pRoot);
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::FindMin()
{
    return tree_minimum(m_pRoot);
}

template<typename T>
void Binary_Search_Tree<T>::Delete(const T& data)
{
    Tree_Node *p = Find(data);

    tree_delete(p);
}

template<typename T>
void Binary_Search_Tree<T>::free_node(Tree_Node *p)
{
    if(p == NULL)
        return ;

    free_node(p->L);
    free_node(p->R);

    p->L = NULL;
    p->R = NULL;
    p->P = NULL;

    delete p;
    p = NULL;

#ifdef _DEBUG
    --cnt;
#endif
}
template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_search(Binary_Search_Tree<T>::Tree_Node *x,const T& data)
{
    if(x == NULL || x->key == data)
    {
        return x;
    }

    if(data < x->key)
    {
        return tree_search(x->L,data);
    }
    else
    {
        return tree_search(x->R,data);
    }
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::iterative_tree_search(Binary_Search_Tree<T>::Tree_Node *x,const T& data)
{
    while(x && x->key != data)
    {
        if(data < x->key)
        {
            x = x->L;
        }
        else
        {
            x = x->R;
        }
    }

    return x;
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_minimum(Binary_Search_Tree<T>::Tree_Node *root)
{
    while(root && root->L)
    {
        root = root->L;
    }

    return root;
}
template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_maximum(Binary_Search_Tree<T>::Tree_Node *root)
{
    while(root && root->R)
    {
        root = root->R;
    }

    return root;
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_successor(Binary_Search_Tree<T>::Tree_Node *x)
{
    //if right_sub_tree is not empty
    if(x->R)
    {
        return tree_minimum(x->R);
    }

    //if ... is empty
    Tree_Node *y = x->P;
    while(y && x == y->R)
    {
        x = y;
        y = y->P;
    }

    return y;
}

template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_predecessor(Binary_Search_Tree<T>::Tree_Node *x)
{
    if(x->L)
    {
        return tree_maximum(x->L);
    }

    Tree_Node *y = x->P;
    while(y && x = y->L)
    {
        x = y;
        y = y->P;
    }

    return y;
}
template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_insert(Binary_Search_Tree<T>::Tree_Node *z)
{
    if(m_pRoot == NULL)
    {
        m_pRoot = z;
    }
    else
    {
        Tree_Node *y = NULL;
        Tree_Node *x = m_pRoot;
        while(x)
        {
            y = x;
            if(z->key < x->key)
            {
                x = x->L;
            }
            else
            {
                x = x->R;
            }
        }

        z->P = y;

        if(z->key < y->key)
        {
            y->L = z;
        }
        else
        {
            y->R = z;
        }
    }

    return z;
}
template<typename T>
typename Binary_Search_Tree<T>::Tree_Node* Binary_Search_Tree<T>::tree_delete(Binary_Search_Tree<T>::Tree_Node *z)
{
    Tree_Node *y = NULL;
    if(!z->L || !z->R)
    {
        y = z;
    }
    else
    {
        y = tree_successor(z);
    }

    Tree_Node *x = NULL;
    if(y->L)
    {
        x = y->L;
    }
    else
    {
        x = y->R;
    }

    if(x)
    {
        x->P = y->P;
    }

    if(!y->P)
    {
        m_pRoot = x;
    }
    else if(y == y->P->L)
    {
        y->P->L = x;
    }
    else
    {
        y->P->R = x;
    }

    if(y != z)
    {
        z->key = y->key;
    }

    return y;
}
#endif

测试代码:

#include "binary_search_tree.h"

int main()
{
    Binary_Search_Tree<int> tree;

    std::cout << "please enter some nums to insert with 1000 ends" << std::endl;
    int y;
    while(std::cin >> y && y != 1000)
    {   
        tree.Insert(y);
    }   

    tree.Display();
        
    Binary_Search_Tree<int>::Tree_Node *p = tree.FindMin();
    if(p)
    {   
        std::cout << "the min is " << p->key << std::endl;
    }   

    p = tree.FindMax();
    if(p)
    {   
        std::cout << "the max is " << p->key << std::endl;
    }   

    std::cout << "please eneter a num to delete" << std::endl;

    int x;
    std::cin >> x;
    tree.Delete(x);

    std::cout << "after delete" << std::endl;
    tree.Display();

    return 0;
}

结果:

please enter some nums to insert with 1000 ends
3 5 6 7 10 12 13 15 16 18 20 23 1000
Node = 3
Node = 5
Node = 6
Node = 7
Node = 10
Node = 12
Node = 13
Node = 15
Node = 16
Node = 18
Node = 20
Node = 23
the min is 3
the max is 23
please eneter a num to delete
5
after delete
Node = 3
Node = 6
Node = 7
Node = 10
Node = 12
Node = 13
Node = 15
Node = 16
Node = 18
Node = 20
Node = 23



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值