一.堆排序
1.将较小的值放在叶子节点
- public static void adjustHeap(int arr[], int i, int length) {
- int temp = arr[i];
-
- for (int k = i * 2 + 1; k < length; k = k + 2 + 1) {
- if (k + 1 < length && arr[k] < arr[k + 1]) {
- k++;// 指向右子结点
- }
- if (arr[k] > temp) {
- arr[i] = arr[k];
- i = k;
- } else {
- break;
- }
- }
- arr[i] = temp;
- }
2.进行排序
- public static void sort(int[] arr) {
- for (int i = arr.length / 2 - 1; i >= 0; i--) {
- adjustHeap(arr, i, arr.length);
- }
- System.out.println(Arrays.toString(arr));//得到大顶堆
-
- for (int i = arr.length - 1; i >= 0; i--) {
- int temp = arr[i];
- arr[i] = arr[0];
- arr[0] = temp;
- adjustHeap(arr, 0, i);
- }
- System.out.println(Arrays.toString(arr));
- }
二.得到哈夫曼编码
1.获得每个字符的数量
- public static List
getNodes(byte[] bytes) { -
- ArrayList
nodes = new ArrayList<>(); -
- HashMap
map = new HashMap<>(); - for (byte b : bytes) {
- Integer count = map.get(b);
- if (count == null) {
- map.put(b, 1);
- } else {
- map.put(b, count + 1);
- }
- }
- for (Map.Entry
entry : map.entrySet()) { - nodes.add(new Node(entry.getKey(), entry.getValue()));
- }
- return nodes;
- }
2.创建哈夫曼树
- public static Node createHuffmanTree(List
nodes) { - while (nodes.size() > 1) {
- Collections.sort(nodes);
-
- Node leftNode = nodes.get(0);
- Node rightNode = nodes.get(1);
-
- Node parent = new Node(null, leftNode.weight + rightNode.weight);
-
- parent.left = leftNode;
- parent.right = rightNode;
-
- nodes.remove(leftNode);
- nodes.remove(rightNode);
-
- nodes.add(parent);
- }
- return nodes.get(0);
- }
3.获得哈夫曼编码
- public static void getCodes(Node node, String code, StringBuilder stringBuilder) {
- StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);
- // 拼接上一轮的code
- stringBuilder1.append(code);
- if (node != null) {
- if (node.date == null) {// 非叶子结点
- // 向左递归
- getCodes(node.left, "0", stringBuilder1);
- // 向右递归
- getCodes(node.right, "1", stringBuilder1);
- } else {
- huffmanCodes.put(node.date, stringBuilder1.toString());
- }
- }
- }
4.进行压缩
- public static byte[] zip(byte[] bytes, Map
huffmanCodes) { -
- StringBuilder stringBuilder = new StringBuilder();
-
- for (byte b : bytes) {
- stringBuilder.append(huffmanCodes.get(b));
- }
-
- int len;
- if (stringBuilder.length() % 8 == 0) {
- len = stringBuilder.length() / 8;
- } else {
- len = stringBuilder.length() / 8 + 1;
- }
- // 存储压缩后的byte数组
- byte[] huffmanCodeBytes = new byte[len];
- int index = 0;
- for (int i = 0; i < stringBuilder.length(); i += 8) {
- String strByte;
- if (i + 8 > stringBuilder.length()) {
- strByte = stringBuilder.substring(i);
- } else {
- strByte = stringBuilder.substring(i, i + 8);
- }
- // 将strByte 转成byte,放入到huffmanCodeBytes
- huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte, 2);
- index++;
- }
- return huffmanCodeBytes;
- }
二.进行解码
1.对压缩后文件进行解码
- public static String byteToBitString(boolean flag,byte b){
-
- int temp=b;
- if (flag){
- temp |=256;// 按位与
- }
- // 返回二进制补码
- String str=Integer.toBinaryString(temp);
- if (flag){
- return str.substring(str.length()-8);
- }else {
- return str;
- }
- }
- public static byte[] decode(Map
huffmanCodes,byte[] huffmanBytes){ -
- StringBuilder stringBuilder = new StringBuilder();
- // 得到对应二进制字符串
- for (int i = 0; i < huffmanBytes.length; i++) {
- byte b = huffmanBytes[i];
- boolean flag=(i== huffmanBytes.length-1);
- stringBuilder.append(byteToBitString(!flag,b));
- }
- // 反向查询
- // 将字符串按照指定哈夫曼编码进行解码
- HashMap
map = new HashMap<>(); - for (Map.Entry
entry : huffmanCodes.entrySet()) { - map.put(entry.getValue(),entry.getKey());
- }
-
- // 存放byte
- ArrayList
list = new ArrayList<>(); -
- for (int i = 0; i < stringBuilder.length(); ) {
- int count=1;
- boolean flag=true;
- Byte b=null;
- while (flag){
- String key = stringBuilder.substring(i, i + count);
- b=map.get(key);
- if (b==null){
- count++;
- }else {
- flag=false;
- }
- }
- list.add(b);
- i+=count;
- }
- byte[] b = new byte[list.size()];
- for (int i = 0; i < b.length; i++) {
- b[i]=list.get(i);
- }
- return b;
- }