可以借助具有FIFO特征的列队来实现
package knowledge; import java.util.ArrayDeque; /** * 三叉链表存储二叉树 * @author [email protected] * @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"进行编码,将它转换成唯一的二进制码,但要求转换出来的二进制码的长度最小。
package knowledge; import java.util.ArrayDeque; /** * 哈夫曼树 * @author [email protected] */ 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 [email protected] */ 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; } }