能夠藉助具備FIFO特徵的列隊來實現 java
package knowledge; import java.util.ArrayDeque; /** * 三叉鏈表存儲二叉樹 * @author liam.huang@foxmail.com * @param <E> */ public class ThreeLinkBinTree<E> { public static class TreeNode{ Object data; TreeNode left; TreeNode right; TreeNode parent; public TreeNode(){ } public TreeNode(Object data){ this.data = data; } public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent){ this.data = data; this.left = left; this.right = right; this.parent = parent; } } //根節點 private static TreeNode rootNode; //以默認的構造器建立二叉樹 public ThreeLinkBinTree(){ this.rootNode = new TreeNode(); } //指定根元素建立二叉樹 public ThreeLinkBinTree(E data){ this.rootNode = new TreeNode(data); } /** * 爲指定節點添加子節點 * @param parent 須要添加子節點的父節點 * @param data 新的子節點數據 * @param isLeft 是否爲左節點 * @return 新增節點 */ public TreeNode addNote(TreeNode parent, E data, boolean isLeft){ if(parent==null){ throw new RuntimeException(parent + "節點爲null,沒法添加子節點"); } if(isLeft && parent.left!=null){ throw new RuntimeException(parent + "節點已有左子節點,沒法添加左子節點"); } if(!isLeft && parent.right!=null){ throw new RuntimeException(parent + "節點已有右子節點,沒法添加右子節點"); } TreeNode newNode = new TreeNode(data); if(isLeft){ parent.left = newNode; }else{ parent.right = newNode; } newNode.parent = parent; return newNode; } //是否爲空 public boolean isEmpty(){ return rootNode.data==null; } //返回根節點 public TreeNode rootNode(){ if(isEmpty()){ throw new RuntimeException("樹爲空,沒法訪問根節點"); } return rootNode; } //返回指定節點(非根節點)的父節點 public E parent(TreeNode node){ if(node==null){ throw new RuntimeException("節點爲null,沒法訪問其父節點"); } return (E) node.parent.data; } //返回指定節點(非葉子)的左子節點 public E leftChild(TreeNode parent){ if(parent==null){ throw new RuntimeException("節點爲null, 沒法添加子節點"); } return (E) (parent.left==null? null : parent.left.data); } public E rightChild(TreeNode parent){ if(parent==null){ throw new RuntimeException("節點爲null, 沒法添加子節點"); } return (E) (parent.right==null ? null : parent.right.data); } //返回二叉樹的深度 public int deep(){ return deep(rootNode); } //每棵子樹的深度爲其全部子樹的最大深度+1 private int deep(TreeNode node){ if(node==null){ return 0; } if(node.left==null && node.right==null){ return 1; }else{ int leftDeep = deep(node.left); int rightDeep = deep(node.right); int max = leftDeep>rightDeep ? leftDeep : rightDeep; return max+1; } } //深度優先遍歷-先序遍歷 public List<TreeNode> preIterator(){ return preIterator(rootNode); } private List<TreeNode> preIterator(TreeNode node){ List<TreeNode> list = new ArrayList<TreeNode>(); list.add(node); if(node.left!=null){ list.addAll(preIterator(node.left)); } if(node.right!=null){ list.addAll(preIterator(node.right)); } return list; } //深度優先遍歷-中序遍歷 public List<TreeNode> inIterator(){ return inIterator(rootNode); } private List<TreeNode> inIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); if(node.left!=null){ list.addAll(inIterator(node.left)); } list.add(node); if(node.right!=null){ list.addAll(inIterator(node.right)); } return list; } //深度優先遍歷-後序遍歷 public List<TreeNode> postIterator(){ return postIterator(rootNode); } private List<TreeNode> postIterator(TreeNode node){ List<TreeNode> list = new ArrayList<TreeNode>(); if(node.left!=null){ list.addAll(postIterator(node.left)); } if(node.right!=null){ list.addAll(postIterator(node.right)); } list.add(node); return list; } //廣度優先遍歷 public List<TreeNode> breadthFirst(){ Queue<TreeNode> queue = new ArrayDeque<TreeNode>(); List<TreeNode> list = new ArrayList<TreeNode>(); //將根元素加入"列隊" if(rootNode!=null){ queue.offer(rootNode); } while(!queue.isEmpty()){ //將該列隊的隊尾元素添加到list中 list.add(queue.peek()); TreeNode p = queue.poll(); if(p.left!=null){ queue.offer(p.left); } if(p.right!=null){ queue.offer(p.right); } } return list; } public static void main(String[] args){ Queue<TreeNode> queue = new ArrayDeque<TreeNode>(); List<TreeNode> list = new ArrayList<TreeNode>(); //將根元素加入"列隊" if(rootNode!=null){ queue.offer(rootNode); } while(!queue.isEmpty()){ //將該列隊的隊尾元素添加到list中 list.add(queue.peek()); TreeNode p = queue.poll(); if(p.left!=null){ queue.offer(p.left); } if(p.right!=null){ queue.offer(p.right); } } System.out.println(list); } }
假設須要把一個字符串"abcdabcaba"進行編碼,將它轉換成惟一的二進制碼,但要求轉換出來的二進制碼的長度最小。 node
package knowledge; import java.util.ArrayDeque; /** * 哈夫曼樹 * @author liam.huang@foxmail.com */ public class HuffmanTree { public static class Node<E>{ E data; double weight; Node leftChild; Node rightChild; public Node(E data, double weight){ this.data = data; this.weight = weight; } public String toString(){ return "Node[data=" + data + ", weight=" + weight + "]"; } } private static Node createTree(List<Node> nodes) { while(nodes.size()>1){ quickSort(nodes); Node left = nodes.get(nodes.size()-1); Node right = nodes.get(nodes.size()-2); Node parent = new Node(null, left.weight + right.weight); parent.leftChild = left; parent.rightChild = right; nodes.remove(nodes.size()-1); nodes.remove(nodes.size()-1); } return nodes.get(0); } private static void quickSort(List<Node> nodes) { subSort(nodes, 0, nodes.size()-1); } private static void subSort(List<Node> nodes, int start, int end) { if(start<end){ Node base = nodes.get(start); int i = start; int j = end+1; while(true){ while(i<end && nodes.get(+i).weight>=base.weight); while(j>start && nodes.get(--j).weight<=base.weight); if(i<j){ swap(nodes, i, j); }else{ break; } } swap(nodes, start, j); subSort(nodes, start, j-1); subSort(nodes, j+1, end); } } private static void swap(List<Node> nodes, int i, int j) { Node tmp; tmp = nodes.get(i); nodes.set(i, nodes.get(i)); nodes.set(j, tmp); } private static List<Node> breadthFirst(Node root) { Queue<Node> queue = new ArrayDeque<Node>(); List<Node> list = new ArrayList<Node>(); if(root!=null){ queue.offer(root); } while(!queue.isEmpty()){ list.add(queue.peek()); Node p = queue.poll(); if(p.leftChild!=null){ queue.offer(p.leftChild); } if(p.rightChild!=null){ queue.offer(p.rightChild); } } return list; } public static void main(String[] args){ List<Node> nodes = new ArrayList<Node>(); nodes.add(new Node("A", 40.0)); nodes.add(new Node("B", 8.0)); nodes.add(new Node("C", 10.0)); nodes.add(new Node("D", 30.0)); nodes.add(new Node("E", 10.0)); nodes.add(new Node("F", 2.0)); Node root = HuffmanTree.createTree(nodes); System.out.println(breadthFirst(root)); } }
b)進行顏色調換和樹旋轉,使之知足紅黑樹特徵 算法
package knowledge; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; import java.util.Queue; /** * 紅黑樹 * @author liam.huang@foxmail.com */ public class RedBlackTree<T extends Comparable> { private static final boolean RED = false; private static final boolean BLACK = true; static class Node{ Object data; Node parent; Node left; Node right; //默認節點顏色爲黑色 boolean color = BLACK; public Node(Object data, Node parent, Node left, Node right){ this.data = data; this.parent = parent; this.left = left; this.right = right; } public String toString(){ return "[data=" + data + ", color=" + color + "]"; } public boolean equals(Object obj){ if(this==obj){ return true; } if(obj.getClass()==Node.class){ Node target = (Node) obj; return data.equals(target.data) && parent==target.parent && left==target.left && right==target.right && color==target.color; } return false; } } private Node rootNode; //兩個構造器用於建立排序二叉樹 public RedBlackTree(){ rootNode = null; } public RedBlackTree(T element){ rootNode = new Node(element, null, null, null); } //添加節點 public void add(T element){ if(rootNode==null){ rootNode = new Node(element, null, null, null); }else{ Node current = rootNode; Node parent = null; int cmp = 0; do{ parent = current; cmp = element.compareTo(current.data); //若是新節點的值大於當前節點的值 if(cmp>0){ //以右節點做爲當前節點 current = current.right; }else{ //若是新節點的值小於當前節點的值,以左節點做爲當前節 current = current.left; } }while(current!=null); //建立新節點 Node newNode = new Node(element, parent, null, null); //若是新節點的值大於父節點的值 if(cmp>0){ //新節點做爲父節點的右節點 parent.right = newNode; }else{ //若是新節的值小於父節點的值,新節點做爲父節點的左節點 parent.left = newNode; } //維護紅黑樹 fixAfterInsertion(newNode); } } //插入節點後修復紅黑樹 private void fixAfterInsertion(Node newNode) { newNode.color = RED; //循環直到newNode的父節點不是根,並且newNode的父節點不是紅色 while(newNode!=null && newNode!=rootNode && newNode.parent.color!=RED){ //若是newNode的父節點是其父節點的左子節點 if(parentOf(newNode)==leftOf(parentOf(parentOf(newNode)))){ //獲取newNode的父節點的兄弟節點 Node bro = rightOf(parentOf(newNode)); //若是newNode的父親節點的兄弟節點是紅色 if(colorOf(bro)==RED){ //將newNode的父節點設爲黑色 setColor(parentOf(newNode), BLACK); //將newNode的父節點的兄弟節點設爲黑色 setColor(bro, BLACK); //將newNode的父節點的父節點設爲紅色 setColor(parentOf(parentOf(newNode)), RED); newNode = parentOf(parentOf(newNode)); }else{//若是newNode的父節點的兄弟節點是黑色 //若是newNode是其父節點的右子節點 if(newNode==rightOf(parentOf(newNode))){ newNode = parentOf(newNode); rotateLeft(newNode); } //把newNode的父節點設爲黑色 setColor(parentOf(newNode), BLACK); //把newNode的父節點的父節點設爲紅色 setColor(parentOf(parentOf(newNode)), RED); rotateRight(parentOf(parentOf(newNode))); } }else{//若是newNode的父親節點是其父節點的右子節點 //獲取newNode的父親節點的父親節點的兄弟節點 Node bro = leftOf(parentOf(parentOf(newNode))); //若是newNode的父親節點的兄弟節點是紅色 if(colorOf(bro)==RED){ //將newNode的父節點設爲黑色 setColor(parentOf(newNode), BLACK); //將newNode的父節點的兄弟節點設爲黑色 setColor(bro, BLACK); //將newNode的父節點的父節點設爲紅色 setColor(parentOf(parentOf(newNode)), RED); //將newNode設爲newNode的父節點的節點 newNode = parentOf(parentOf(newNode)); }else{//若是newNode的父節點的兄弟節點是黑色 //若是newNode是其父節點的左子節點 if(newNode==leftOf(parentOf(newNode))){ //將newNode的父節點設爲newNode newNode = parentOf(newNode); rotateRight(newNode); } //把newNode的父節點設爲黑色 setColor(parentOf(newNode), BLACK); //把newNode的父節點的父節點設爲紅色 setColor(parentOf(parentOf(newNode)), RED); rotateLeft(parentOf(parentOf(newNode))); } } } //將根節點設爲黑色 rootNode.color = BLACK; } private Node parentOf(Node node) { return node==null ? null : node.parent; } private Node leftOf(Node node){ return node==null ? null : node.left; } private Node rightOf(Node node){ return node==null ? null : node.right; } private boolean colorOf(Node node){ return node==null? BLACK : RED; } private void setColor(Node node, boolean bv){ if(node!=null){ node.color = bv; } } /** * 執行以下轉換 * node r * r node * q q * @param node */ public void rotateLeft(Node node){ if(node!=null){ Node rn = node.right; Node q = rn.left; node.right = q; if(q!=null){ q.parent = node; } rn.parent = node.parent; if(node.parent==null){ rootNode = rn; }else if(node.parent.left==node){ node.parent.left = rn; }else{ node.parent.right = rn; } rn.left = node; node.parent = rn; } } /** * 執行以下轉換 * node l * l node * q q * @param node */ public void rotateRight(Node node){ if(node!=null){ Node ln = node.left; Node q = ln.right; node.left = q; if(q!=null){ q.parent = node; } ln.parent = node.parent; if(node.parent==null){ rootNode = ln; }else if(node.parent.left==node){ node.parent.left = ln; }else{ node.parent.right = ln; } ln.right = node; node.parent = ln; } } //刪除節點 public void remove(T element){ //獲取要刪除的節點 Node target = getNode(element); //若是被刪除的節點的左子樹/右子樹都不爲空 if(target.left!=null && target.right!=null){ //找到target節點中序遍歷的前一個節點 //s用於保存target節點中的左子樹中最大的節點 Node s = target.left; //搜索target節點的左子樹中最大的節點 while(s.right!=null){ s = s.right; } //用s節點來代替p節點 target.data = s.data; target = s; } //開始修復它的替換節點,若是該替換節點不爲null Node replacement = target.left!=null ? target.left : target.right; if(replacement!=null){ //讓replacement的parent指向target的parent replacement.parent = target.parent; //若是target的parent爲null,代表target自己就是根節點 if(target.parent==null){ rootNode = replacement; }else if(target==target.parent.left){//若是target是其父節點的左子節點 //讓target的父節點left指向replacement target.parent.left = replacement; }else{ //讓target的父節點right指向replacement target.parent.right = replacement; } //完全刪除target節點 target.left = target.right = target.parent = null; if(target.color = BLACK){ fixAfterDeletion(replacement); } }else if(target.parent==null){ rootNode = null; }else{ //target沒有子節點,把它當成虛的替換節點 //修復紅黑樹 if(target.color==BLACK){ fixAfterDeletion(target); } if(target.parent!=null){ //若是target是其父節點的左子節點 if(target==target.parent.left){ // target.parent.left = null; }else if(target==target.parent.right){ target.parent.right = null; } target.parent = null; } } } //根據給定的值搜索節點 private Node getNode(T element) { //從根節點開始搜索 Node p = rootNode; while(p!=null){ int cmp = element.compareTo(p.data); //若是搜索的值小於當前p節點的值 if(cmp<0){ //向左子樹搜索 p = p.left; }else if(cmp>0){ //向右子樹搜索 p = p.right; }else{ return p; } } return null; } //刪除節點後修復紅黑樹 private void fixAfterDeletion(Node node) { //直到node不是根節點,且node的顏色是黑色 while(node!=rootNode && colorOf(node)==BLACK){ //若是node是其父節點的左子節點 if(node==leftOf(parentOf(node))){ //獲取node節點父節點的兄弟節點 Node bro = rightOf(parentOf(node)); //若是bro節點是紅色 if(colorOf(bro)==RED){ //將bro節點設爲黑色 setColor(bro, BLACK); //將bro的父節點設爲紅色 setColor(parentOf(node), RED); rotateLeft(parentOf(node)); //再次將bro設爲node的父節點的右子節點 bro = rightOf(parentOf(node)); } //若是node的兩個子節點都是黑色 if(colorOf(leftOf(node))==BLACK && colorOf(rightOf(bro))==BLACK){ setColor(bro, RED); node = parentOf(node); }else{ if(colorOf(rightOf(bro))==BLACK){ setColor(leftOf(bro), BLACK); setColor(bro, RED); rotateRight(bro); bro = rightOf(parentOf(node)); } setColor(bro, colorOf(parentOf(node))); setColor(parentOf(node), BLACK); setColor(rightOf(node), BLACK); rotateLeft(parentOf(node)); node = rootNode; } }else{ Node bro = leftOf(parentOf(node)); if(colorOf(bro)==RED){ setColor(bro, BLACK); setColor(parentOf(node), RED); rotateRight(parentOf(node)); bro = leftOf(parentOf(node)); } if(colorOf(rightOf(node))==BLACK && colorOf(leftOf(node))==BLACK){ setColor(bro, RED); node = parentOf(node); }else{ if(colorOf(leftOf(bro))==BLACK){ setColor(rightOf(bro), BLACK); setColor(bro, RED); rotateLeft(bro); bro = leftOf(parentOf(node)); } setColor(bro, colorOf(parentOf(node))); setColor(parentOf(node), BLACK); setColor(leftOf(bro), BLACK); rotateRight(parentOf(node)); node = rootNode; } } } setColor(node, BLACK); } //實現中序遍歷 public List<Node> inIterator(){ return inInterator(rootNode); } private List<Node> inInterator(Node rootNode) { List<Node> list = new ArrayList<Node>(); //遞歸處理左子樹 if(rootNode.left!=null){ list.addAll(inInterator(rootNode.left)); } //處理根節點 list.add(rootNode); //遞歸處理右子樹 if(rootNode.right!=null){ list.addAll(inInterator(rootNode.right)); } return list; } //廣度優先遍歷 public List<Node> breadthFirst(){ Queue<Node> queue = new ArrayDeque<Node>(); List<Node> list = new ArrayList<Node>(); if(rootNode!=null){ queue.offer(rootNode); } while(!queue.isEmpty()){ list.add(queue.peek()); Node p = queue.poll(); if(p.left!=null){ queue.offer(p.left); } if(p.right!=null){ queue.offer(p.right); } } return list; } }