二分搜索树
-
根节点大于左子树所有节点的值,小于右子树所有节点的值,不包含重复元素
-
二分搜索树有着高效的插入、删除、查询操作。
-
查询快的原因(因为查询的时候只需要查询一半数据)
前序遍历:先访问改节点,再访问左右节点
private void preOrder(Node node){ if (node==null){ return; } System.out.println(node.e); preOrder(node.left); preOrder(node.right); }
中序遍历
在中间访问
public void inOrder(){ inOrder(root); } private void inOrder(Node node){ if (node==null){ return; } inOrder(node.left); System.out.println(node.e); inOrder(node.right); }
后续遍历
public void LastOrder(){ LastOrder(root); } private void LastOrder(Node node){ if (node==null){ return; } LastOrder(node.left); LastOrder(node.right); System.out.println(node.e); }
二分搜索树实现
// extends comparable 表示存储的元素可以进行比较 public class BST<E extends Comparable<E>> { private class Node{ public E e; public Node left,right; public Node(E e){ this.e=e; left=null; right=null; } } private Node root; private int size; public BST(){ root=null; size=0; } public int size(){ return size; } public boolean isEmpty(){ return size==0; } public void add(E e){ root=add(root,e); } //添加 private Node add(Node node, E e){ //终止条件 if (node==null){ size++; return new Node(e); } if (e.compareTo(node.e)<0){ node.left=add(node.left,e); } else if (e.compareTo(node.e)>0) { node.right = add(node.right, e); } return node; } //包含方法 public boolean contains(E e){ return contains(root,e); } private boolean contains(Node node,E e){ if (node==null){ return false; } if (e.compareTo(node.e)==0){ return true; } else if (e.compareTo(node.e)<0) { return contains(node.left,e); }else{ return contains(node.right,e); } } //前序遍历 public void preOrder(){ preOrder(root); } private void preOrder(Node node){ if (node==null){ return; } System.out.println(node.e); preOrder(node.left); preOrder(node.right); } }
二分搜索树的非递归遍历
//使用栈来模拟 public void preOrderNR(){ Stack<Node> nodes = new Stack<>(); nodes.push(root); while (!nodes.isEmpty()){ Node cur=nodes.pop(); System.out.println(cur.e); if (cur.right!=null) { nodes.push(cur.right); } if (cur.left!= null) { nodes.push(cur.left); } } }
二分搜索树的层序遍历
/使用队列来完成 public void levelOrder(){ LinkedList<Node> nodes = new LinkedList<>(); nodes.add(root); while (!nodes.isEmpty()){ Node cur=nodes.remove(); System.out.println(cur.e); if (cur.left!= null){ nodes.add(cur.left); } if (cur.right!=null){ nodes.add(cur.right); } } }
广度优先遍历在查找的时候更快,最短路径
//查找二分搜索树的最大值(最右边)或者最小值(最左边)
public E minNum(){
if (size==0) {
throw new IllegalArgumentException("二叉搜索树为空");
}
return minimum(root).e;
}
private Node minimum(Node node){
if (node.left==null){
return node;
}
return minimum(node.left);
}
//删除二叉搜索树中的最小值
public E removeMin(){
removeMin(root);
return minNum();
}
private Node removeMin(Node node){
if (node.left==null){
Node rNode=node.right;
node.right=null;
size--;
return rNode;
}
node.left= removeMin(node.left);
return node;
}
//二叉搜索树删除节点
public void remove(E e){
root=remove(root,e);
}
private Node remove(Node node,E e){
if (node==null){
return null;
}
if (e.compareTo(node.e)<0){
remove(node.left,e);
}
if (e.compareTo(node.e)>0){
remove(node,e);
}else {
if (node.left == null) {
Node rNode = node.right;
node.right = null;
size--;
return rNode;
}
if (node.right == null) {
Node lNode = node.left;
node.left = null;
size--;
return lNode;
}
//左右都不是零的情况
Node successor = minimum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left;
node.right = node.left = null;
return successor;
}
return node;
}