赞
踩
为什么要用树结构?
将数据使用树结构存储后,出奇的高效
n = n0 + n1 + n2 + n3 = n1 + 2n2 + 3n3 + 1
class Node {
E e;
Node left;
Node right;
}
====================================================
天然地柜结构
n = n0 + n1 + n2
B:分支数
B + 1 = n ----> B = n - 1 -----> B = n0 + n1 + n2 - 1
B = 2n2 + n1
n0 + n1 + n2 - 1 = 2n2 + n1 ----> n0 = n2 + 1
当n位奇数时 n1 = 0;
n = n0 + n1 + n2
= n0 + 0 + (n0-1)
= 2n0 - 1
当n位偶数时,n1 = 1
n = 2n0
Binary Search Tree 排序后的二叉树
条件
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; } //向BST中添加新元素 public void add(E e){ if(root == null){ root = new Node(e); size++; } } //向以node为root的BST插入e,递归 private void add(Node node,E e){ //终止条件 if(e.equals(node.e)) return; else if(e.compareTo(node.e) < 0 && node.left == null){ node.left = new Node(e); size++; return; } else if(e.compareTo(node.e) > 0 && node.right == null){ node.right = new Node(e); size++; return; } //递归调用 if(e.compareTo(node.e) < 0) add(node.left,e); if(e.compareTo(node.e) > 0) add(node.right,e); } }
以上的逻辑在root中添加 e 需要单独处理,可以进行改进
public void add(E e){ root = add(root,e); } //向以node为root的BST插入e,递归 //返回添加的新Node 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; }
//TODO 查找元素e public boolean contain(E e){ return contain(root,e); } private boolean contain(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 contain(node.right,e); }else { //e.compareTo(node.e) < 0 return contain(node.left,e); } }
前序遍历 中序遍历 后续遍历
都是深度优先的遍历
//TODO Order
//1 preOrder
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);
}
//2 inOrder
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);
}
前序遍历:1 2 4 5 7 8 3 6
中序遍历:4 2 7 5 8 1 3 6
后序遍历:4 7 8 5 2 6 3 1
层次遍历:1 2 3 4 5 6 7 8
略
调试code
public static void main(String[] args) { BST2<Integer> bst = new BST2<>(); int[] nums = {5, 3, 6, 8, 4, 2}; for(int num: nums) bst.add(num); / // 5 // // / \ // // 3 6 // // / \ \ // // 2 4 8 // / // bst.PreOrder(); System.out.println(); bst.InOrder(); System.out.println(bst); }
不用递归的方式实现Tree的遍历
//TODO Order 不用Recursion的方式,用Stack //1 preOrder public void PreOrder() throws IllegalAccessException { PreOrderNR(root); } private void PreOrderNR(Node node) throws IllegalAccessException { if (node == null) { return; } Stack<Node> Stack = new ArrayStack<>(); Stack.push(node); while (!Stack.isEmpty()){ Node pop = Stack.pop(); System.out.println(pop.e); if (pop.right != null) { Stack.push(pop.right); } if(pop.left != null){ Stack.push(pop.left); } } }
层序遍历 也叫 广度遍历
第一层 0 有的也有叫1
第二层1
…
可以采用Queue的方式实现广度遍历
//TODO LevelOrder public void levelOrder(){ if(root == null) return; //import java.util.LinkedList; //import java.util.Queue; Queue<Node> q = new LinkedList<>(); q.add(root); while (!q.isEmpty()) { Node remove = q.remove(); System.out.println(remove.e); if (remove.left != null) { q.add(remove.left); } else if (remove.right != null) { q.add(remove.right); } } }
//TODO 寻找BST中的最小元素 public E minimun() throws IllegalAccessException { if(size == 0) throw new IllegalAccessException("BST is empty"); Node minimum = minimum(root); return minimum.e; } private Node minimum(Node node){ if (node.left == null) { return node; } return minimum(node.left); } //TODO max of the BST public E maxmum() throws IllegalAccessException { if(root == null) throw new IllegalAccessException("BST is empty"); Node maxmum = maxmum(root); return maxmum.e; } public Node maxmum(Node node){ if (node.right == null) { return node; } return maxmum(node.right); }
//TODO delete the max public E removeMax() throws IllegalAccessException { E maxmum = maxmum(); root = removeMax(root); return maxmum; } private Node removeMax(Node node){ if (node.right == null) { Node leftNode = node.left; node.left = null; size--; return leftNode; } node.right = removeMax(node.right); return node; } //TODO delete the min public E removeMin() throws IllegalAccessException { E minimum = minimun(); root = removeMin(root); return minimum; } private Node removeMin(Node node){ if (node.left == null) { Node rightNode = node.right; node.right = null; size--; return rightNode; } node.left = removeMin(node.left); return node; }
子节点isNull 删除很容易
左右节点都不为空,
//TODO delete the elements 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) { node.left = remove(node.left,e); return node; } else if(e.compareTo(node.e) > 0){ node.right = remove(node.right,e); return node; }else { // e.compareTo(node.e) == 0 //带删除节点左子树为空 if (node.left == null) { Node right = node.right; node.right = null; size--; return right; } //带删除节点右子树为空 if (node.right == null) { Node left = node.left; node.left = null; size--; return left; } //Hibbard Deletion Node successor = minimum(node.right); successor.right = removeMin(node.right);//size-- successor.left = node.left; node.left = node.right = null; return successor; } }
也可以用d.left 中的最大值 来填充 一样保持BST
叶子结点外,所有节点都必须有两个子节点
除最后一层节点外,其他各层节点都必须有两个子节点,且最后一层节点左排列
Set<E>
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; } // 向二分搜索树中添加新的元素e public void add(E e){ if(root == null){ root = new Node(e); size ++; } else add(root, e); } // 向以node为根的二分搜索树中插入元素e,递归算法 private void add(Node node, E e){ if(e.equals(node.e)) return; else if(e.compareTo(node.e) < 0 && node.left == null){ node.left = new Node(e); size ++; return; } else if(e.compareTo(node.e) > 0 && node.right == null){ node.right = new Node(e); size ++; return; } if(e.compareTo(node.e) < 0) add(node.left, e); else //e.compareTo(node.e) > 0 add(node.right, e); } }
向以node为根的二分搜索树中插入元素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;
// 看以node为根的二分搜索树中是否包含元素e, 递归算法
// 看以node为根的二分搜索树中是否包含元素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 // e.compareTo(node.e) > 0
return contains(node.right, e);
}
// 二分搜索树的前序遍历 public void preOrder(){ preOrder(root); } // 前序遍历以node为根的二分搜索树, 递归算法 private void preOrder(Node node){ if(node == null) return; System.out.println(node.e); preOrder(node.left); preOrder(node.right); } @Override public String toString(){ StringBuilder res = new StringBuilder(); generateBSTString(root, 0, res); return res.toString(); } // 生成以node为根节点,深度为depth的描述二叉树的字符串 private void generateBSTString(Node node, int depth, StringBuilder res){ if(node == null){ res.append(generateDepthString(depth) + "null\n"); return; } res.append(generateDepthString(depth) + node.e + "\n"); generateBSTString(node.left, depth + 1, res); generateBSTString(node.right, depth + 1, res); } private String generateDepthString(int depth){ StringBuilder res = new StringBuilder(); for(int i = 0 ; i < depth ; i ++) res.append("--"); return res.toString(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。