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

    二叉搜索树是以一颗二叉树来组织的。这棵树可以使用链表数据结构表示。每个节点除了key和卫星数据外。每个节点包含属性left、right、parent。二叉搜索树中树,如果x是一个节点,则x.left.key < x.key < x.right.key。

    中序遍历、前序遍历、后续遍历

    InorderTreeWalk(x)
    {
        if(x != null)
        {
            InorderTreeWalk(x.left);
            print x.key;
            InorderTreeWalk(x.right);
        }
    }
    PreorderTreeWalk(x)
    {
        if(x != null)
        {
            print x.key;
            InorderTreeWalk(x.left);
            InorderTreeWalk(x.right);
        }
    }
    PostorderTreeWalk(x)
    {
        if(x != null)
        {
            InorderTreeWalk(x.left);
            InorderTreeWalk(x.right);
            print x.key;
        }
    }

    查询-递归

    TreeSearch(x, k)
    {
        if(x == null || k == x.key)
            return x;
        if(k < x.key)
            return TreeSearch(x.left, k);
        return TreeSearch(x.right, k);
    }

    查询-循环

    TreeSearch(x, k)
    {
        while(x != null && k != x.key)
        {
            if(k < x.key)
                x = x.left;
            else
                x = x.right;
        }
         return x;
    }

    最大

    TreeMaximum(x)
    {
        while(x != null)
        {
                x = x.right;
        }
         return x;
    }

    最小

    TreeMinimum(x)
    {
        while(x != null)
        {
                x = x.left;
        }
         return x;
    }

    后继和前驱

    右子树不空,则x后继为右子树最小节点。右子树为空,那x后继为空,或就是其祖先,并且这个祖先左子节点仍是x的祖先。总的来说就是,后继就是x大的最小的数。

    TreeSuccessor(x)
    {
      if(x.right != null)
        return TreeMinimum(x.right);
      y=x.parent;
      while(y != null && x==y.right)
      {
        x=y;
        y=y.parent
      }
      return y;
    }

    插入

    TreeInsert(T, z)
    {
      y=null;
      x=T.root;
      while(x != null)
      {
        y=x;
        if(z.key < x.key)
          x=x.left;
        else
          x=x.right;
    } x.parent
    =y; if(y == null) T.root=z; else if(z.key < y.key) y.left=z; else y.right=z; }

    删除z

    1. 如果z没有孩子,删除之z=null
    2. 如果z只有一个孩子,z.child<l or r>.p=p.p; z.p.child<l or r>=z.child<l or r>.p
    3. 如果有两个孩子,则z的后继y需要占领z,然后在考虑将z的子树与y的子树合并问题
    Transplant(T, u, v)
    {
        if (u.parent == null)
            t.root = v
        else if (u == u.parent.left)
            u.p.left = v;
        else
            u.p.right = v;
        if (v != null)
            v.parent = u.partent;
    }
    TreeDelete(T, z)
    {
        if (z.left == null)
            Transplant(T, z, z.right);
        else if (z.right == null)
            Transplant(T, z, z.left);
        else
        {
            y = TreeMinimum(z.right);//z有双子,则后继为右侧最小
            if (y.parent != z)
            {
                Transplant(T, y, y.right);
                y.right = z.right;
                y.right.parent = y;
            }
            Transplant(T, z, y);
            y.left = z.left;
            y.left.parent = y;
        }
    }

     C#范例

    //object[0..3],分别是parent, left, right, key
    static void Main(string[] args)
    {
        //树根
        object[] head = new object[4];
        head[3] = 9;
        foreach (int i in new int[] { 4,7,3,5,8,6})
        {
            object[] z = new object[4];
            z[3] = i;
            //插入
            TreeInsert(head, z);
        }
        //中序输出
        InorderTreeWalk(head);
        //查找
        var s = TreeSearch(head, 4);
        var d = TreeSuccessor(s);
        //删除
        TreeDelete(head, s);
    }
    //删除
    private static void TreeDelete(object[] head, object[] s)
    {
        if (s[1] == null)
            Transplant(head, s, (object[])s[2]);
        else if (s[2] == null)
            Transplant(head, s, (object[])s[1]);
        else
        {
            var y = TreeSuccessor(s);//y一定没有左子树
            if (y[0] == s)//y是s的右子树,又没有左子树、可能有右子树
            {
                //y安到s的位置
                Transplant(head, s, y);
                //s的左树安到y上
                y[1] = s[1];
                ((object[])(y[1]))[0] = y;
            }
            else
            {
                Transplant(head, y, (object[])y[2]);
                //将s的右树接到y上
                y[2] = s[2];
                ((object[])(y[2]))[0] = y;
    
                //y安到s的位置
                Transplant(head, s, y);
                //s的左树安到y上
                y[1] = s[1];
                ((object[])(y[1]))[0] = y;
            }
        }
    }
    //用子树v替换掉子树u
    private static void Transplant(object[] head, object[] u, object[] v)
    {
        var T = head;
        if (u[0] == null)
        {
            T = v;
        }
        else if(((object[])(u[0]))[1] == u)
        {
            ((object[])(u[0]))[1] = v;
        }
        else
        {
            ((object[])(u[0]))[2] = v;
        }
        if (v != null)
            v[0] = u[0];
    }
    
    //查找
    private static object[] TreeSearch(dynamic head, int v)
    {
        var x = head;
        if (x == null || x[3] == v)
            return x;
        if (x[3] > v)
        {
            return TreeSearch(x[1], v);
        }
        else
        {
            return TreeSearch(x[2], v);
        }
    }
    
    //后继
    private static object[] TreeSuccessor(object[] T)
    {
        var x = T;
        if (x[2] != null)
        {
            return TreeMin(x[2]);
        }
        dynamic y = x[0];
        while (y != null && x == y[2])
        {
            x = y;
            y = y[0];
        }
        return y;
    }
    //最小值
    private static object[] TreeMin(dynamic T)
    {
        var x = T;
        while (x[1] != null)
            x = x[1];
        return x;
    }
    //中序输出
    private static void InorderTreeWalk(dynamic T)
    {
        if (T != null)
        {
            Console.Write(T[3].ToString()+" ");
            InorderTreeWalk(T[1]);
            InorderTreeWalk(T[2]);
        }
    }
    //插入
    static void TreeInsert(object[] T, object[] z)
    {
        var x = T;
        object[] y = null;
        while (x != null)
        {
            y = x;//循环完成后,记录x的父节点
            if ((int)(x[3]) < (int)(z[3]))
            {
                x = (object[])(x[2]);
            }
            else
            {
                x = (object[])(x[1]);
            }
        }
        if (y == null) //x是根,并且是空树
        {
            T = z;
        }
        else if ((int)(z[3]) < (int)(y[3]))
        {
            y[1] = z;
        }
        else
            y[2] = z;
        z[0] = y;
    }
  • 相关阅读:
    XML及XML的解析
    单例设计模式(Singleton)的优化
    Java反射初识
    TCP协议的简单应用一
    Java中实现线程同步的三种方法
    Java集合框架Map接口
    JDK1.8新特性之Stream类初识
    Java JDK1.8新特性之四大函数式接口
    tomcat 启动报 找不到 StrutsPrepareAndExecuteFilter。。
    easyjweb ejs 2014.2.25
  • 原文地址:https://www.cnblogs.com/qiusuo/p/5218777.html
Copyright © 2011-2022 走看看