二叉搜索树及其模拟实现

1.二叉搜索树(二叉排序树)的定义
二叉搜索树或者是空树,或者具有以下性质的二叉树:
① 若左子树为空,则左子树上所有结点的关键字值均小于它的根节点的关键字值。
② 若右子树为空,则右子树上所有结点的关键字值均大于它的根节点的关键字值。
③左右子树本身又是一颗二叉搜索树。
2.二叉搜索树的查找
查找思路为:若待查找数据元素的关键字值等于二叉搜索树根节点的关键字值,则查找成功;若待查找数据元素的关键字值大于二叉搜索树根节点的关键字值,则在根节点的右子树中继续查找;若待查找数据元素的关键字值小于二叉搜索树根节点的关键字值,则在根节点的左子树中继续查找;
3.二叉搜索树的插入
插入的思路为:若二叉排序树为空,则将新节点作为根插入;若二叉搜索树非空,则将新节点的关键字值与根节点的关键字值相比较,若等于根节点关键字值,则不插入;若大于根节点的关键字值,则插入到二叉搜索树的右子树中;若小于根节点的关键字值,则插入到二叉搜索树的左子树中。
4.二叉搜索树的删除
删除思路为:先查找,如果删除的元素不存在,则直接返回;若存在则分其它情况
①叶子结点
a.只有根节点,则直接删除根节点并置空。
b.叶子结点是左子树和叶子结点是右子树
②只有左孩子
③只有右孩子
④左右孩子都有
这里写图片描述
5.模拟实现

#include <iostream>  
#include <cstdio>  
#include <cstdlib>  
using namespace std;

typedef int ElemType;
template<class T>
struct BinaryTreeNode
{
    T key;        //关键字  
    BinaryTreeNode<T> *left;   //左孩子  
    BinaryTreeNode<T> *right;  //右孩子  
    BinaryTreeNode<T> *parent; //父节点  
    BinaryTreeNode(const T&x)
        :key(x),
        left(NULL),
        right(NULL),
        parent(NULL)
    {}
};

template<class  T>
struct BinaryFindTree
{
    typedef BinaryTreeNode<T> Node;
public:
    BinaryFindTree() //无参构造函数
        :_root(NULL)
    {}
    BinaryFindTree(T* a, size_t n) //构造函数
    {
        size_t index = 0;
        CreateTree(a, n, index);
    }
    void PreOrderHelp() //前序遍历
    {
        _PreOrderHelp(_root);
        cout << endl;
    }
    void _PreOrderHelp(const Node *root)const //前序遍历
    {
        if (root != NULL)
        {
            cout << root->key << " ";
            _PreOrderHelp(root->left);
            _PreOrderHelp(root->right);
        }
    }
    void InOrderHelp() //中序遍历
    {
        _InOrderHelp(_root);
        cout << endl;
    }
    void _InOrderHelp(const Node *root)const //中序遍历
    {
        if (root != NULL)
        {
            _InOrderHelp(root->left);
            cout << root->key << " ";
            _InOrderHelp(root->right);
        }
    }
    void PostOrderHelp() //后序遍历
    {
        _PostOrderHelp(_root);
        cout << endl;
    }
    void _PostOrderHelp(const Node* root)const //后序遍历
    {
        if (root != NULL)
        {
            _PostOrderHelp(root->left);
            _PostOrderHelp(root->right);
            cout << root->key << " ";
        }
    }
    Node* Insert(Node *&root, const T& key) //插入  
    {   
        Node *newroot = new Node(key);
        if (root == NULL) //空树  
        {
            newroot->left = NULL;
            newroot->right = NULL;
            newroot->parent = root;
            root = newroot;
            _root = root;
        } 
        Node* ccur = root;
        Node* cur = root;
        while (ccur != NULL)
        {
            if (ccur->key > key)
            {
                cur = ccur;
                ccur = ccur->left;
            }
            else if (ccur->key < key)
            {
                cur = ccur;
                ccur = ccur->right;
            }
            else
                break;
        }
        if (cur->left == NULL && cur->key > key)//左孩子
        {
            cur->left = newroot;
            newroot->left = NULL;
            newroot->right = NULL;
            newroot->parent = cur;
            ccur = root;
        } 
        if (cur->right == NULL && cur->key < key) //右孩子
        {
            cur->right = newroot;
            newroot->left = NULL;
            newroot->right = NULL;
            newroot->parent = cur;
            ccur = root;
        }
        return root;
    }

    Node* Search(Node* root, const T& key) //查找元素,找到返回关键字的结点指针,没找到返回NULL  
    {
        if (root == NULL)
            return root;
        if (root->key > key) //查找左子树  
            return Search(root->left, key);
        else if (root->key < key)
            return Search(root->right, key);
    }

    Node* SearchMin(Node* root) //查找最小关键字,空树时返回NULL  
    {
        if (root == NULL)
            return root;
        while (root->left != NULL)
            root = root->left;
        return root;
    }

    Node* SearchMax(Node* root) //查找最大关键字,空树时返回NULL  
    {
        if (root == NULL)
            return root;
        while (root->right != NULL) //迭代  
            root = root->right;
        return root;
    }

    Node* SearchPredecessor(Node* cur)  //查找前驱  
    {
        if (cur == NULL) //空  
            return cur; 
        if (cur->left != NULL) //若存在左孩子,前驱是其左子树中最大的 
            return SearchMax(cur->left);
        Node* prev = cur->parent;
        while (prev != NULL && cur == prev->left)
        {
            cur = prev;
            prev = cur->parent;
        }
        return prev;
    }

    Node* SearchSuccessor(Node* cur)//查找后继  
    {
        if (cur == NULL)  //空  
            return cur;
        if (cur->right != NULL) //若存在右孩子,后继是其右子树中最小的  
            return SearchMin(cur->right);
        Node* prev = cur->parent;
        while (prev != NULL && cur == prev->right)
        {
            cur = prev;
            prev = cur->parent;
        }
        return prev;
    }

    int DeleteNode(Node *&root, const T& key)
    {
        Node* q; 
        Node* p = Search(root, key);//查找到要删除的结点 
        if (p == NULL)
            return 0;
        //一共有四种情况,该节点是叶子节点、只有左孩子、只有右孩子、左右孩子都有  
        //叶子结点  
        if (p->left == NULL && p->right == NULL)
        { 
            if (p->parent == NULL) //只有根节点 
            {
                free(p);
                root = NULL;
            }
            else
            {
                //删除的结点是左孩子  
                if (p->parent->left == p)
                    p->parent->left = NULL;
                else //右孩子
                    p->parent->right = NULL;
                free(p);
            }
        }
        //左孩子  
        else if (p->left != NULL && p->right == NULL)
        {
            p->left->parent = p->parent;
            //如果删除是根结点  
            if (p->parent == NULL)
                root = p->left;
            //父节点的左孩子  
            else if (p->parent->left == p)
                p->parent->left = p->left;
            else
                p->parent->right = p->left;
            free(p);
        }
        //右孩子  
        else if (p->right != NULL && p->left == NULL)
        {
            p->right->parent = p->parent;
            //如果删除是根结点  
            if (p->parent == NULL)
                root = p->right;
            //是父节点的左孩子  
            else if (p->parent->left == p)
                p->parent->left = p->right;
            else
                p->parent->right = p->right;
            free(p);
        }
        //左右孩子都有  
        //该结点的后继结点肯定无左子树  
        //删掉后继结点,后继结点的值代替该结点  
        else
        {
            //找到要删除结点的后继  
            q = SearchSuccessor(p);
            ElemType temp = q->key;    //暂存后继结点的值  
            //删除后继结点  
            DeleteNode(root, q->key);
            p->key = temp;
        }
        return 1;
    }
Node* CreateTree(T* a, size_t n, size_t& index) //创建子树
{
    Node* root = _root = NULL;
    while (index < n)
    {
        Insert(root, a[index]);
        index++;
    }
    return root;
}
protected:
    Node* _root;
};

void test()
{
    typedef BinaryTreeNode<int> Node;
    int Array[11] = { 15, 6, 18, 3, 7, 17, 20, 2, 4, 13, 9 };
    //int Array[5] = { 5, 3, 6, 2 ,4};
    BinaryFindTree<int> T2;
    size_t index = 0;
    Node* ret = T2.CreateTree(Array, sizeof(Array) / sizeof(Array[0]), index);
    T2.InOrderHelp();
    T2.PreOrderHelp();
    T2.PostOrderHelp();
    //cout << T2.Search(ret, 20) << endl;
    //T2.Insert(ret, 1);
    //cout << T2.SearchMin(ret) << endl;
    //cout << T2.SearchMax(ret) << endl;
    T2.DeleteNode(ret, 3);
    T2.InOrderHelp();
}
int main()
{
    test();
    system("pause");
    return 0;
}

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值