zoukankan      html  css  js  c++  java
  • 二叉排序树

    二叉排序树定义:

    1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

    2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

    3. 它的左、右子树也分别为二叉排序树。

    二叉排序树的常用方法:

    添加结点:类似二叉树

    遍历:所有遍历和普通二叉树一样

    删除结点:重点!!!!

    1.删除叶子节点

    思路:

    (1)找到要删除的结点:targetNode

    (2)找到targetNode的父结点parent

    (3)确定targetNode是parent的左子结点还是右子结点

    (4)根据情况进行删除

    2.删除只有一颗子树的结点

    思路:

    (1)找到要删除的结点:targetNode

    (2)找到targetNode的父结点parent

    (3)确定targetNode的子树是左子树还是右子树

    (4)确定targetNode是parent的左子结点还是右子结点

    (5)如果targetNode只有左子树

    因为targetNode的左子树都小于targetNode的值,其中最大的就是targetNode.left(即所有小的中挑大的)

    5.1 如果targetNode是parent的左子结点

    parent.left=target.left

    5.2 如果targetNode是parent的右子结点

    parent.right=targetNode.left 

    (6)如果targetNode只有右子树

    因为targetNode的右子树都大于targetNode的值,其中最小的就是targetNode.right(即所有大的中挑小的)

    6.1 如果targetNode是parent的左子结点

    parent.left=targetNode.right

    6.2 如果targetNode是parent的右子结点

    parent.right=targetNode.right

    总结:删除只有一颗子树的结点,在该结点的子树中找到可以替代该子树的结点,替换掉即可

    3.删除有两棵子树的结点

    思路:

    (1)找到要删除的结点targetNode

    (2)找到targetNode的父结点parent

    (3)从targetNode的右子树找到最小的结点

    (4)创建临时变量temp保存最小结点的值

    (5)删除最小结点

    (6)targetNode.value=temp

    思路:删除有两颗子树的结点。首先该结点肯定是大于左边所有结点且小于右边所有结点(即中间值)

    找到最接近该结点的值的结点替代要删除的结点即可(左边结点中最大的或者右边结点中最小的)

    完整代码如下:对于代码应该认真体会找父结点,递归等思想的实现

    //构造结点
        public class Node
        {
            public int value;
            public Node left;
            public Node right;
            public Node(int value)
            {
                this.value = value;
            }
            //查找要删除的结点
            public Node search(int value)
            {
                if (value == this.value)
                {
                    //找到 就是该点
                    return this;
                }
                else if (value < this.value)
                {
                    //查找的值小于当前结点 递归左子树查找
                    //如果左子结点为空
                    if (this.left == null)
                    {
                        return null;
                    }
                    return this.left.search(value);
                }
                else
                {
                    //查找的值不小于当前结点 右子树递归
                    //右子树为空
                    if (this.right == null)
                    {
                        return null;
                    }
                    return this.right.search(value);
                }
            }
            //查找要删除结点的父结点
            public Node searchParent(int value)
            {
                //如果当前结点就是要删除的结点的父结点
                if (this.left != null && this.left.value == value ||
                    (this.right != null && this.right.value == value))
                {
                    return this;
                }
                else
                {
                    //如果要查找的值小于当前结点的值,且当前结点的左子结点不为空
                    if (value < this.value && this.left != null)
                    {
                        //递归左子树查找
                        return this.left.searchParent(value);
                    }
                    //如果要查找的值大于当前结点的值,且当前结点的右子结点不为空
                    else if (value >= this.value && this.right != null)
                    {
                        //递归右子树查找
                        return this.right.searchParent(value);
                    }
                    //没有父结点
                    else
                    {
                        return null;
                    }
                }
            }
            public void add(Node node)
            {
                if (node == null)
                {
                    return;
                }
                //判断传入的结点值和当前子树根结点的关系
                //当前结点的值大于传入的值
                if (node.value < this.value)
                {
                    //如果左子树为空
                    if (this.left == null)
                    {
                        this.left = node;
                    }
                    else
                    //如果左子树不为空
                    {
                        //向左递归
                        this.left.add(node);
                    }
                }
                else//传入的值大于等于当前结点的值
                {
                    //右子树为空
                    if (this.right == null)
                    {
                        this.right = node;
                    }
                    //右子树不为空
                    else
                    {
                        //向右递归
                        this.right.add(node);
                    }
                }
            }
            public void midOrder()
            {
    
                if (left != null)
                {
                    this.left.midOrder();
                }
                Console.WriteLine(this.toString());
                if (right != null)
                {
                    this.right.midOrder();
                }
    
            }
            public string toString()
            {
                return "结点值为:" + this.value;
            }
        }
    
        //构造二叉排序树
        public class BinarySortTree
        {
            public Node root;
            //添加结点
            public void add(Node node)
            {
                if (root == null)
                {
                    root = node;
                }
                else
                {
                    root.add(node);
                }
            }
            //中序遍历
            public void midOrder()
            {
                if (root != null)
                {
                    root.midOrder();
                }
                else
                {
                    Console.WriteLine("当前二叉排序树为空");
                }
            }
            //查找要删除的结点
            public Node search(int value)
            {
                if (root == null)
                {
                    return null;
                }
                else
                {
                    return root.search(value);
                }
            }
            //查找要删除结点的父结点
            public Node searchParent(int value)
            {
                if (root == null)
                {
                    return null;
                }
                else
                {
                    return root.searchParent(value);
                }
            }
            //删除结点
            public void delNode(int value)
            {
                if (root == null)
                {
                    return;
                }
                else
                {
                    //需要删除的目标结点
                    Node targetNode = search(value);
                    if (targetNode == null)
                    {
                        return;
                    }
                    //如果这颗二叉排序树只有一个结点
                    if(root.left==null&&root.right==null)
                    {
                        root = null;
                        return;
                    }
                    //去查找targetNode的父结点
                    Node parent = searchParent(value);
                    //删除的是叶子节点
                    if(targetNode.left==null&&targetNode.right==null)
                    {
                        //判断target是父结点的左子结点还是右子结点
                        //要删除结点是父结点的左子结点
                        if(parent.left!=null&&parent.left.value==value)
                        {
                            parent.left = null;
                        }
                        //要删除结点是父结点的右子结点
                        else if(parent.right!=null&&parent.right.value==value)
                        {
                            parent.right = null;
                        }
                    }
                    //删除两颗子树的结点
                    else if(targetNode.left!=null&&targetNode.right!=null)
                    {
                        //从右边找最小的
                        int minVal = Min(targetNode.right);
                        targetNode.value = minVal;
                    }
                    //删除只有一颗子树的结点
                    else
                    {
                        //如果要删除的结点有左子结点
                        //targetNode有左子结点
                        if (targetNode.left != null)
                        {
                            if (parent != null)
                            {
                                //target是parent的左子结点
                                if (parent.left.value == value)
                                {
                                    parent.left = targetNode.left;
                                }
                                else//target是parent的右子结点
                                {
                                    parent.right = targetNode.left;
                                }
                            }
                            else
                            {
                                root = targetNode.left;
                            }
                        }
                        else//要删除的结点有右子结点
                        {
                            if (parent != null)
                            {
                                //target是parent的左子结点
                                if (parent.left.value == value)
                                {
                                    parent.left = targetNode.right;
                                }
                                else//target是parent的右子结点
                                {
                                    parent.right = targetNode.right;
                                }
                            }
                            else
                            {
                                root = targetNode.right;
                            }
                        }
                    }
                }
            }
    
            //找到以node结点为根节点的二叉排序树最小结点的值,并删除
            public int Min(Node node)
            {
                Node target = node;
                //循环查找左节点
                while(target.left!=null)
                {
                    target = target.left;
                }
                //target指向了最小结点,并删除
                delNode(target.value);
                return target.value;
            }
        }
  • 相关阅读:
    十、CI框架之通过参数的办法输出URI路径
    九、CI框架之将URI转为数组原型
    八、CI框架之输出URI路径,相当于GET
    七、CI框架之分配变量数组,循环输出
    六、CI框架之分配变量
    五、CI框架之通过带路径的view视图路径访问
    四、CI框架之通过URL路径访问C中的函数
    三、CI框架之一个最简单的页面
    二、CI框架之MCV模型
    一、CI框架(CodeIgniter)简介
  • 原文地址:https://www.cnblogs.com/TheLin/p/13928889.html
Copyright © 2011-2022 走看看