二叉搜索树

二叉搜索树是以一颗二叉树来组织的。这棵树可以使用链表数据结构表示。每个节点除了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;
}

 

posted on 2016-02-25 23:26  峰入云  阅读(359)  评论(0编辑  收藏  举报

导航