起飞就起飞

数据结构之二叉树

Posted on By baixiao

转自zwl同学。

二叉树

和链表一样,动态数据结构
二叉树具有唯一根节点
二叉树每个节点最多有两个孩子
二叉树每个节点最多有一个父亲
二叉树具有天然的递归结构
每个节点的左子树也是二叉树
每个节点的右子树也是二叉树
二叉树不一定是满的
一个节点也是二叉树
null也是二叉树
class Node {
    E e;
    Node left;
    Node right;
}


二分搜索树

Binary Search Tree

二分搜索树是二叉树
二分搜索树的每个节点的值:
    大于其左子树的所有节点的值
    小于其右子树的所有节点的值
每一棵子树也是二分搜索树
储存的元素必须有可比较性    


二分搜索树添加元素


我们的二分搜索树不包含重复元素
如果想包含重复元素的话,只需要定义:
	左子树小于等于节点;或者右子树大于等于节点
注意:我们之前讲的数组和链表,可以有重复元素	

二分搜索树的遍历


前序遍历 // 28,16,13,22,30,29,42
中序遍历,结果是顺序的 // 13,16,22,28,29,30,42
后序遍历 // 13,22,16,29,42,30,28

二分搜索树前序遍历的非递归实现


28入栈
28出栈
30,16入栈
16出栈
22,13入栈
13出栈

二分搜索树的层序遍历



28入队
28出队
16,30入队
16出队
13,22入队

深度优先和广度优先


二分搜索树的最小值和最大值


二分搜索树删除节点

对于带删除的节点,左子树或右子树为空,好处理,较难的是删除一个左右子树都不为空的节点
1962年,Hibbard提出 - Hibbard Deletion
删除左右都有孩子的节点d
找到 s = min(d -> right)
s 是 d 的后继
s -> rigth = delMin(d -> right)
s -> left = d -> left
删除d,s是新的子树的根



或者找s的前驱


floor & ceil

二分搜索树的floor和ceil
floor // 比45小的最大的元素
ceil // 比45大的最小的元素
与前驱和后继不同的是floor和ceil可以不在二分搜索树中

rank & select

rank // 58是排名第几的元素?
select // 排名第10的元素是谁?

维护size的二分搜索树


维护depth的二分搜索树


支持重复元素的二分搜索树


前驱 & 后继

前驱(successor)
后继(predecessor)
如果一个二叉树中序遍历顺序为1,2,3,4,5
3的前驱是2,3的后继是4

集合

set

class Node {
    E e;
    Node left;
    Node right;
}

class Node {
    E e;
    Node next;
}
Set<E>
void add(E)
void remove(E)
boolean contains(E)
int getSize()
boolean isEmpty()

h代表树的高度

                LinkedListSet       BSTSet  平均     最差
增add           O(n)                 O(h)   O(logn)  O(n)
查contains      O(n)                 O(h)   O(logn)  O(n)
删remove        O(n)                 O(h)   O(logn)  O(n)

二分搜索树的复杂度分析





logn和n的差距

有序集合中的元素具有顺序性 // 基于搜索树的实现
无序集合中的元素没有顺序性 // 基于哈希表的实现