目录
使用树的思想解决实际问题
- 堆排序
- 赫夫曼树
- 赫夫曼编码
- 二叉树
堆排序
步骤
![](https://img-blog.csdnimg.cn/3d5ae1a8c0b44c029eab55e378665f42.png)
![](https://img-blog.csdnimg.cn/490c67ee756d4d7c8455bf92d3565fc3.png)
![](https://img-blog.csdnimg.cn/b2c54e4d04c54313b1be327c1c05f816.png)
![](https://img-blog.csdnimg.cn/7dc7696bc27747fc84a4c3f9e3ed302d.png)
![](https://img-blog.csdnimg.cn/15f48d79b08a416aaddbeebe5e871855.png)
![](https://img-blog.csdnimg.cn/82c6c00484864098a0a9c3bd6cdbfa72.png)
![](https://img-blog.csdnimg.cn/7dc907c262a141ae9797d88bfcfcf691.png)
![](https://img-blog.csdnimg.cn/99945228f0b24d93b1dfe3bbbd123522.png)
代码实现
public class HeapSort {
public static void main(String[] args) {
int[] arr = {4, 6, 8, 5, 9};
/*
//分次实例
adjustHeap(arr, 1, arr.length);
System.out.println("第一次排序" + Arrays.toString(arr));
adjustHeap(arr, 0, arr.length);
System.out.println("第二次排序" + Arrays.toString(arr));
*/
// 先对数组的大顶堆排序
int count = 0;
for (int i = arr.length / 2 - 1; i >= 0 ; i--) {
adjustHeap(arr, i, arr.length);
System.out.println("第" + (++count) + "次排序" + Arrays.toString(arr));
}
// 根据排好的堆排序
// 如果是大顶堆, 则第一个数是最大的, 最后一个数是最小的, 所以交换头和尾
// 并重新进行大顶堆排序得到第二位大的数和倒数第二位小的并交换, 循环直到全部排完
int temp;
for (int i = arr.length - 1; i > 0; i--) {
temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//从头排起
adjustHeap(arr, 0, i);
}
System.out.println("Array : " + Arrays.toString(arr));
}
/**
* 用于将数组以大顶堆树的方式存储
* @param arr 要被排序的数组
* @param i 起始节点
* @param len 要排序的个数
*/
public static void adjustHeap(int[] arr, int i, int len){
int temp = arr[i];
// 定位到 数组第i位 在树中的位置 -> 而且是左节点
for (int j = i * 2 + 1; j < len; j = j * 2 + 1) {
// 如果存在右节点且 左节点小于有节点, 则指针指向右节点
if( j + 1 < len && arr[j] < arr[j + 1]){
j++;
}
// 根据大顶堆定理, 越往下的值应该越小, 所以
// 指针指的节点一定比 temp 节点上的值大,小的话直接符合定理退出了不需要交换
if (arr[j] > temp){
// 把大数放到当前叶子节点顶部
arr[i] = arr[j];
// i 指向 k 用于继续循环比较是否有比当前数大的
i = j;
}else {
break;
}
}
//循环结束后, 原来在顶端的数可能被替换了, 所以需要放回到被替换的位子上去
arr[i] = temp;
}
}
赫夫曼树
基本介绍
概念
构建思路
![](https://img-blog.csdnimg.cn/2def1b0365b24d07a7548b68653b49cd.png)
![](https://img-blog.csdnimg.cn/1fce8d25ad674b048dbe290d232658b9.png)
代码实现
package Part11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class HuffmanTree {
public static void main(String[] args) {
int[] arr = { 13, 7, 8, 3, 29, 6, 1 };
Node finalNode = createHuffmanTree(arr);
System.out.println();
finalNode.preSort();
}
public static Node createHuffmanTree(int[] arr){
//存到集合方便排序
List<Node> arrayList = new ArrayList<>();
for (int i : arr) {
arrayList.add(new Node(i));
}
System.out.println(arrayList);
// size() == 1 的时候代表已经全部树化
while (arrayList.size() > 1){
// 排序
Collections.sort(arrayList);
// 拿出最小的前两个节点
Node left = arrayList.get(0);
Node right = arrayList.get(1);
//组成新的节点
Node newNode = new Node(left.value + right.value);
newNode.left = left;
newNode.right = right;
//用完就删掉
arrayList.remove(left);
arrayList.remove(right);
// 新节点添加进去
arrayList.add(newNode);
System.out.println(arrayList);
}
// 当只剩下一个节点时已经树化成功
return arrayList.get(0);
}
}
//创建树节点
class Node implements Comparable<Node>{
int value;
Node left;
Node right;
public void preSort(){
System.out.println(this);
if (this.left != null){
this.left.preSort();
}
if (this.right != null){
this.right.preSort();
}
}
public Node(int value) {
this.value = value;
}
@Override
public String toString() {
return "Node{" +
"value=" + value + '}';
}
// 实现Comparable用于比较节点之间的权值用于排序
// this.value - o.value 代表从小到大排序
// -(this.value - o.value) 代表从大到小排序
@Override
public int compareTo(Node o) {
return this.value - o.value;
}
}
赫夫曼编码
详见另一篇笔记:
二叉树
详见另一篇笔记: