DEMO地址:
https://github.com/zhaopingfu/MDataStruct/blob/master/src/com/pf/%E6%A0%91/BintraySortTree.java
1、路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
带权路径长度最小的二叉树为哈弗曼树。
哈弗曼树的构造
1、先把有权值的叶子节点按照从小到大的顺序排列成一个有序序列,即:A5,E10,B15,D30,C40。
2、取头两个最小权值的节点作为一个新的节点N1的两个子节点,注意相对较小的是左节点,这里就是A为N1的左节点,E为N1的右节点,如图所示,新节点的权值为两个叶子节点权值的和:5 + 10 = 15。
3、将N1替换A与E,插入有序序列中,保持从小到大排列,即:N1 15,B15,D30,C40。
4、重复步骤2。将N1与B作为一个新节点N2的两个子节点,N2的权值为:15 + 15 = 30。
5、将N2替换N1与B,插入有序序列中。保持从小到大排列。即:N2 30,D30,C40。
6、重复步骤2。将N2与D作为一个新节点N3的两个子节点,N3的权值为:30 + 30 = 60。
7、将N3替换N2与D,插入有序序列中,保持从小到大排列。即:C40,N3 60。
8、重复步骤2。将C与N3作为一个新节点T的两个字节点,由于T是根节点,所以哈弗曼树完成构造。
/** * @author zhaopf * @version 1.0 * @QQ: 1308108803 * @date 2017年12月20日 */ public class TreeNode<T> { /** * 父节点 */ protected TreeNode<T> parent; /** * 左节点 */ protected TreeNode<T> leftChild; /** * 数据 */ protected T data; /** * 右节点 */ protected TreeNode<T> rightChild; public TreeNode() { } public TreeNode(T data) { if (data == null) { throw new IllegalArgumentException(); } this.data = data; } /** * 添加节点 * * @param data * @return */ public TreeNode<T> put(T data) { throw new RuntimeException(); } /** * 查找节点 * * @param data * @return */ public TreeNode<T> searchNode(T data) { throw new RuntimeException(); } /** * 删除节点 * * @param data * @return */ public TreeNode<T> removeNode(T data) { TreeNode<T> node = searchNode(data); return removeNode(node) ? node : null; } /** * 删除一个节点 * * @param node */ public boolean removeNode(TreeNode<T> node) { throw new RuntimeException(); } public TreeNode<T> getLeftChild() { return leftChild; } public void setLeftChild(TreeNode<T> leftChild) { this.leftChild = leftChild; if (leftChild != null) { leftChild.setParent(this); } } public T getData() { return data; } public void setData(T data) { this.data = data; } public TreeNode<T> getRightChild() { return rightChild; } public void setRightChild(TreeNode<T> rightChild) { this.rightChild = rightChild; if (rightChild != null) { rightChild.setParent(this); } } public TreeNode<T> getParent() { return parent; } public void setParent(TreeNode<T> parent) { this.parent = parent; } } /** * @author zhaopf * @version 1.0 * @QQ: 1308108803 * @date 2017年12月24日 * 哈弗曼树 * <p> * 45(1) 90(1) 65(2) 85(2) 75(4) * 65(2) 85(2) T(2) 75(4) * T(2) 75(4) T(4) * T(4) T(6) * T(10) * <p> * ------------------T(10) * ----T(4)-----------------------T(6) * 65(2) 85(2) T(2) 75(4) * ----------------------45(1)-------90(1) */ public class HaffManTree<T> extends TreeNode<T> implements Comparable<HaffManTree<T>> { private static final String EMPTY_DATA = "**"; /** * 根节点 */ private HaffManTree<T> root; /** * 权 */ private int weight; public HaffManTree(T data, int weight) { super(data); if (weight <= 0) { throw new IllegalArgumentException(); } this.weight = weight; this.root = this; } /** * 添加一个节点 * 相同数据的会筛掉(不是相同权) * * @param data 数据 * @param weight 权 * @return */ public boolean put(T data, int weight) { if (data == null || weight <= 0) { return false; } // 拿到之前的节点 Queue<HaffManTree<T>> queue = showHaffManTree(root); List<HaffManTree<T>> list = new ArrayList<>(Arrays.asList(new HaffManTree<>(data, weight))); if (queue != null && !queue.isEmpty()) { list.addAll(queue); } // 重新构造树 createHaffManTree(list); return true; } @Override public HaffManTree<T> removeNode(T data) { if (data == null) { throw new IllegalArgumentException(); } // 先查找 HaffManTree<T> result = searchNode(data); // 再删除 return removeNode(result) ? result : null; } @Override public boolean removeNode(TreeNode<T> node) { if (node == null) { return false; } // 拿到之前的节点 Queue<HaffManTree<T>> queue = showHaffManTree(root); if (queue == null || queue.isEmpty()) { return false; } // 删除节点 if (!queue.remove(node)) { return false; } // 重新构造树 List<HaffManTree<T>> haffManTreeList = new ArrayList<>(); haffManTreeList.addAll(queue); createHaffManTree(haffManTreeList); return true; } /** * 查找节点 * * @param data * @return */ @Override public HaffManTree<T> searchNode(T data) { if (data == null) { return null; } // 队列的方式,先进先出,有数据往后面添加 Queue<HaffManTree<T>> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()) { HaffManTree<T> tree = queue.poll(); // 找到了直接返回 if (data.equals(tree.getData()) || data == tree.getData()) { return tree; } if (tree.getLeftChild() != null) { queue.offer(tree.getLeftChild()); } if (tree.getRightChild() != null) { queue.offer(tree.getRightChild()); } } return null; } /** * 创建哈弗曼树,返回根节点 * 相同数据的会筛掉(不是相同权) * * @param haffManTreeList * @return 返回根节点 */ public HaffManTree<T> createHaffManTree(List<HaffManTree<T>> haffManTreeList) { if (haffManTreeList == null || haffManTreeList.size() < 1) { return null; } // 筛选,拿到合格的数据 List<HaffManTree<T>> qualifiedList = filterNode(haffManTreeList); while (qualifiedList.size() > 1) { // 根据权值排序 Collections.sort(qualifiedList); // 构造新的节点 HaffManTree<T> left = qualifiedList.get(0); HaffManTree<T> right = qualifiedList.get(1); HaffManTree<T> parent = new HaffManTree(EMPTY_DATA, left.weight + right.weight); parent.setLeftChild(left); parent.setRightChild(right); qualifiedList.remove(left); qualifiedList.remove(right); qualifiedList.add(parent); } root = qualifiedList.get(qualifiedList.size() - 1); return qualifiedList.get(qualifiedList.size() - 1); } /** * 筛选不符合条件的节点 * * @param haffManTreeList * @return */ private List<HaffManTree<T>> filterNode(List<HaffManTree<T>> haffManTreeList) { if (haffManTreeList == null || haffManTreeList.isEmpty()) { return null; } // 把data相同的筛掉 List<T> datas = new ArrayList<>(); Iterator<HaffManTree<T>> it = haffManTreeList.iterator(); while (it.hasNext()) { HaffManTree<T> h = it.next(); // 之前已经有的和内容是空数据的筛掉 if (datas.contains(h.getData()) || EMPTY_DATA.equals(h.getData())) { it.remove(); } else { datas.add(h.getData()); } } return haffManTreeList; } /** * 二叉树的层级遍历,拿到一个层级遍历好的队列,直接顺序遍历即可 * * @param rootNode * @return */ public Queue<HaffManTree<T>> showHaffManTree(HaffManTree<T> rootNode) { if (rootNode == null) { return null; } // 采用队列的方式保存节点 Queue<HaffManTree<T>> queue = new LinkedList<>(); Queue<HaffManTree<T>> result = new LinkedList<>(); queue.offer(rootNode); while (!queue.isEmpty()) { HaffManTree<T> tree = queue.poll(); result.offer(tree); if (tree.getLeftChild() != null) { queue.offer(tree.getLeftChild()); } if (tree.getRightChild() != null) { queue.offer(tree.getRightChild()); } } return result; } /** * 获取哈夫曼编码 * 坐节点都为0,右节点都为1 * * @param haffManTree * @return */ public String getHaffManCode(HaffManTree<T> haffManTree) { if (haffManTree == null || haffManTree.getParent() == null) { return null; } Stack<Integer> resultStack = new Stack<>(); while (haffManTree != null && haffManTree.getParent() != null) { HaffManTree<T> parent = haffManTree.getParent(); // 如果当前是左子节点就为0 if (parent.getLeftChild() != null && parent.getLeftChild() == haffManTree) { resultStack.add(0); } // 如果当前是右子节点就为1 else if (parent.getRightChild() != null && parent.getRightChild() == haffManTree) { resultStack.add(1); } haffManTree = parent; } if (!resultStack.isEmpty()) { StringBuffer sb = new StringBuffer(""); while (!resultStack.isEmpty()) { sb.append(resultStack.pop() + ""); } return sb.toString(); } return null; } @Override public int compareTo(HaffManTree<T> o) { if (this.weight > o.weight) { return 1; } else if (this.weight < o.weight) { return -1; } return 0; } @Override public HaffManTree<T> getLeftChild() { return (HaffManTree<T>) leftChild; } public void setLeftChild(HaffManTree<T> leftChild) { this.leftChild = leftChild; if (leftChild != null) { leftChild.setParent(this); } } @Override public HaffManTree<T> getRightChild() { return (HaffManTree<T>) rightChild; } public void setRightChild(HaffManTree<T> rightChild) { this.rightChild = rightChild; if (rightChild != null) { rightChild.setParent(this); } } @Override public HaffManTree<T> getParent() { return (HaffManTree<T>) parent; } public void setParent(HaffManTree<T> parent) { this.parent = parent; } public HaffManTree<T> getRoot() { return root; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } }