Binary Search Tree
也被成为 ordered binary tree(有序二叉树)或 sorted binary tree(排序二叉树),有如下性质:
- 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
- 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点。
和数组,链表的比较
数据:查找快 O(1),插入慢O(N) 需要移动插入点之后的所有数据。
链表:查找慢 O(N) ,插入快 O(1) 每次查找都需要遍历一遍
于是作为平衡的Binary Search Tree出现了
查找 平均O(logN) 最差O(N)
插入 平均O(logN) 最差O(N)
JAVA实现
首先定义Node,最少包含3个属性,左节点,右节点和值。
public class Node {
public Object data;
public Node left;
public Node right;
public Node(Object o) {
this.data = o;
}
}
前序遍历
按照 root ー> left subtree ー> right subtree 的顺序访问节点。
递归实现
public void printPreOrder(Node n) {
if (n == null) {
return;
}
System.out.println(n.data);
if (n.left != null) {
printPreOrder(n.left);
}
if (n.right != null) {
printPreOrder(n.right);
}
}
非递归实现
public void printPreOrderWithoutRecursion(Node n) {
if (n == null) {
return;
}
Stack<Node> s = new Stack<Node>();
Node current = n;
while (current != null || !s.isEmpty()) {
while (current != null) {
System.out.println(current.data);
s.push(current);
current = current.left;
}
if (!s.empty()) {
current = s.pop();
current = current.right;
}
}
}
中序遍历
按照 left subtree ー> root ー> right subtree 的顺序访问节点。
递归实现
public void printMidOrder(Node n) {
if (n == null) {
return;
}
if (n.left != null) {
printMidOrder(n.left);
}
System.out.println(n.data);
if (n.right != null) {
printMidOrder(n.right);
}
}
非递归实现
public void printMidOrderWithoutRecursion(Node n) {
if (n == null) {
return;
}
Stack<Node> s = new Stack<Node>();
Node current = n;
while (current != null || !s.isEmpty()) {
while (current != null) {
s.push(current);
current = current.left;
}
if (!s.empty()) {
current = s.pop();
System.out.println(current.data);
current = current.right;
}
}
}
后序遍历
按照 left subtree ー> right subtree ー> root 的顺序访问节点。
递归实现
public void printAftOrder(Node n) {
if (n == null) {
return;
}
if (n.left != null) {
printAftOrder(n.left);
}
if (n.right != null) {
printAftOrder(n.right);
}
System.out.println(n.data);
}
非递归实现
后序遍历的非递归实现方法有好几种,其中的一个思路是在node中增加一个标志位来记录是否是第一次访问,如果是第一次访问就再次入栈并查找right subtree,只有当right subtree也查找完成之后第二次入栈的时候再打印。
public class Node {
public Object data;
public Node left;
public Node right;
public boolean isFirst;
public Node(Object o) {
this.data = o;
}
}
public void printAftOrderWithoutRecursion_1(Node n) {
if (n == null) {
return;
}
Stack<Node> s = new Stack<Node>();
Node current = n;
while (current != null || !s.isEmpty()) {
while (current != null) {
current.isFirst = true;
s.push(current);
current = current.left;
}
if (!s.empty()) {
current = s.pop();
if (current.isFirst) {
current.isFirst = false;
s.push(current);
current = current.right;
} else {
System.out.println(current.data);
current = null;
}
}
}
}