二叉搜索树
二叉搜索树是以一颗二叉树来组织的。这棵树可以使用链表数据结构表示。每个节点除了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
- 如果z没有孩子,删除之z=null
- 如果z只有一个孩子,z.child<l or r>.p=p.p; z.p.child<l or r>=z.child<l or r>.p
- 如果有两个孩子,则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; }