zoukankan      html  css  js  c++  java
  • 二叉搜索树

    一、定义和性质:

    1、定义

    二叉查找树(Binary Search Tree),又被称为二叉搜索树。

    它是特殊的二叉树:

    对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。那么,这棵树就是二叉查找树。

    2、性质

    二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:

    1、每个结点都有一个作为搜索依据的关键码(key),所有结点的关键码互不相同。

    2、左子树(如果非空)上所有结点的关键码都小于根结点的关键码。

    3、右子树(如果非空)上所有结点的关键码都大于根结点的关键码。

    4、左子树和右子树也是二叉搜索树。

    5、结点左子树上所有关键码小于结点关键码;

    6、右子树上所有关键码大于结点关键码;

    7、若从根结点到某个叶结点有一条路径,路径左边的结点的关键码不一定小于路径上的结点的关键码。

    8、如果对一棵二叉搜索树进行中序遍历,可以按从小到大的顺序,将各结点关键码排列起来,所以也称二叉搜索树为二叉排序树。

    二、二叉搜索树的实现

    #include <iostream>
    
    using namespace std;
    
    struct BST_Node
    {
        BST_Node *left;
        BST_Node *right; 
        BST_Node *parent;
        int key;
    };
    
    
    //中序遍历,按顺序输出
    void InOrder_Tree_Walk(BST_Node *x)
    {
        if (x != NULL)
        {
            InOrder_Tree_Walk(x->left);
            cout << x->key << " ";
            InOrder_Tree_Walk(x->right);
        }
    }
    
    //递归查找
    BST_Node *D_Tree_Search(BST_Node *x, int k)
    {
        if ((x == NULL) || (k == x->key))
            return x;
        if (k < x->key)
            return D_Tree_Search(x->left, k);
        else
            return D_Tree_Search(x->right, k);
    }
    
    //迭代查找
    BST_Node *Iterative_Tree_Search(BST_Node *x, int k)
    {
        while ((x != NULL) && (k != x->key))
        {
            if (k < x->key)
                x = x->left;
            else
                x = x->right;
        }
    
        return x;
    }
    
    //迭代法求最小值
    BST_Node *Iterative_Tree_Minimum(BST_Node *x)
    {
        while (x->left != NULL)
            x = x->left;
        return x;
    }
    
    
    //递归法求最小值
    BST_Node *D_Tree_Minimum(BST_Node *x)
    {
        if (x->left == NULL)
            return x;
        else
            return D_Tree_Minimum(x->left);
    
    }
    
    //迭代法求最大值
    BST_Node *Iterative_Tree_Maximum(BST_Node *x)
    {
        while (x->right != NULL)
            x = x->right;
        return x;
    }
    
    //递归法求最大值
    BST_Node *D_Tree_Maximum(BST_Node *x)
    {
        if (x->right == NULL)
            return x;
        else
            return D_Tree_Maximum(x->right);
    
    }
    
    BST_Node *Tree_Successor(BST_Node *Root, int k)
    {
        BST_Node *x = D_Tree_Search(Root, k);
    
        if (x->right != NULL)
            return Iterative_Tree_Minimum(x->right);
        else
        {
            BST_Node *y = x->parent;
            while ((y != NULL) && (x == y->right))//y==NULL  返回根节点的双亲,表示无后继节点
            {                                     //x != y->right 表示前面一串节点是当前y的左孩子  
                x = y;                             //此时的y是后继  
                y = y->parent;
            }
    
            return y;
        }
    }
    
    BST_Node *Tree_Predecessor(BST_Node *Root , int k)
    {
        BST_Node *x = D_Tree_Search(Root, k);
    
        if (x->left != NULL)//若左孩子非空,左孩子的最大值就是前驱
            return Iterative_Tree_Maximum(x->left);
        else//若左孩子为空
        {
            BST_Node *y = x->parent;  //依次向上找到整体作为左子树的双亲节点,即为前驱
            while ((y != NULL) && (x == y->left))
            {
                x = y;
                y = y->parent;
            }
    
            return y;
        }
    }
    
    //迭代法插入
    BST_Node *Iterative_Tree_Insert(BST_Node *Root, int k)
    {
        BST_Node *z = new BST_Node;
        z->key = k;
        z->left = z->right = z->parent = NULL;
    
        BST_Node *y = NULL;
        BST_Node *x = Root;
    
        while (x != NULL)//x,y两个指针向下移动,直到x为NULL,这个NULL占据位就是z要放置的地方
        {
            y = x;//当前x节点存到y,遍历指针y作为x的双亲
            if (z->key < x->key)
                x = x->left;
            else
                x = x->right;
        }
    
        z->parent = y;//将y作为z的双亲
    
        if (y == NULL)//此时二叉树为空
            Root = z;
        else if (z->key < y->key)//如果z关键字小于z的双亲y的关键字,则z作为y的左孩子
            y->left = z;          //否则作为右孩子
        else
            y->right = z;
    
    
        return Root;
    }
    
    //递归法插入
    BST_Node *D_Tree_Insert(BST_Node *Root, int k)
    {
        if (!Root)
        {//若原树为空,生成并返回一个节点的二叉搜索树 
            Root->key = k;
            Root->left = NULL;
            Root->right = NULL;
        }   
        else //开始找要插入元素的位置 
        {
            if (k <= Root->key)//递归插入左子树  
                Root->left = D_Tree_Insert(Root->left, k);
    
            else              //递归插入右子树  
                Root->right = D_Tree_Insert(Root->right, k);
        }
    
        return Root;
    
    }
    
    //有数组A[]建立二叉搜索树
    BST_Node *Establish_Tree(int *A, int Length)
    {
        BST_Node *Root = NULL;
    
        for (int i = 0; i < Length; ++i)
            Root = Iterative_Tree_Insert(Root, A[i]);
    
        return Root;
    
    }
    
    //一棵子树替代另一棵子树
    void Transplant(BST_Node *Root, BST_Node *u, BST_Node *v)
    {
    
    
        if (u->parent == NULL)//u为根节点
            Root = v;
        else if (u = u->parent->left)//u是左子树
            u->parent->left = v;
        else
            u->parent->right = v;  //u是右子树
    
        if (v != NULL)     //更新双亲节点,左右子树节点待更新
            v->parent = u->parent;
    }
    
    //删除节点
    BST_Node *Tree_Delete(BST_Node *Root, int k)
    {
        BST_Node *z  = D_Tree_Search(Root, k);
    
        if (z->left == NULL)
            Transplant(Root, z, z->right);
        else if (z->right == NULL)
            Transplant(Root, z, z->left);
        else
        {
            //寻找z节点后继节点
            BST_Node *y = Iterative_Tree_Minimum(z->right);
    
            if (y->parent != z)//右孩子不是z的后继
            {
                Transplant(Root, y, y->right);//将后继的右孩子替代后继,并更新y节点的右孩子
                y->right = z->right;
                y->right->parent = y;
            }
    
            Transplant(Root, z, y);//用y替代z,并更新y的左孩子
            y->left = z->left;
            y->left->parent = y;
    
        }
    
    
        return Root;
    }
    
    
    int main()
    {
        int A[] = { 3, 10, 2, 5, 9, 7, 4, 1, 6, 8 };
        int Length = sizeof(A) / sizeof(A[0]);
    
        BST_Node *Root;
        Root = Establish_Tree(A, Length);
    
        cout << "中序遍历输出所有节点值:";
        InOrder_Tree_Walk(Root);
        cout << endl;
    
        cout << "4的后继是:" << Tree_Successor(Root, 4)->key << endl;
        cout << "7的前驱是:" << Tree_Predecessor(Root, 7)->key << endl;
    
        cout << "迭代法的最小值是:" << Iterative_Tree_Minimum(Root)->key << endl;
        cout << "递归法的最小值是:" << D_Tree_Minimum(Root)->key << endl;
    
        cout << "迭代法的最大值是:" << Iterative_Tree_Maximum(Root)->key << endl;
        cout << "递归法的最大值是:" << D_Tree_Maximum(Root)->key << endl;
    
        cout << "迭代法插入4:";
        Root = Iterative_Tree_Insert(Root, 4);
        cout << "中序遍历输出所有节点值:";
        InOrder_Tree_Walk(Root);
        cout << endl;
    
        cout << "递归法插入8:";
        Root = D_Tree_Insert(Root, 8);
        cout << "中序遍历输出所有节点值:";
        InOrder_Tree_Walk(Root);
        cout << endl;
    
        cout << "删除5:";
        Root = Tree_Delete(Root, 5);
        cout << "中序遍历输出所有节点值:";
        InOrder_Tree_Walk(Root);
        cout << endl;
    
        system("pause");
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    客户端入手分析异步更新机制
    前面PRM实例所使用到的MasterPage
    FCKeditor.Net_2.2安全修正版
    PRM–endRequest事件
    PageRequestManager类
    客户端访问PageMethod
    使用ASPJPEG组件生成缩略图
    使用js实现广告切换
    动态添加UpdatePannel
    MSMQ(Microsoft Message Queue,微软消息队列) Asp.Net 简单示例
  • 原文地址:https://www.cnblogs.com/yangquanhui/p/4937455.html
Copyright © 2011-2022 走看看