第十一章 树结构实际应用

目录

堆排序

步骤

代码实现

赫夫曼树

基本介绍

概念

构建思路

代码实现

赫夫曼编码

二叉树


使用树的思想解决实际问题

  1. 堆排序
  2. 赫夫曼树
    1. 赫夫曼编码
  3. 二叉树

堆排序

步骤

代码实现

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;
    }
}


赫夫曼树

基本介绍

概念

构建思路

代码实现

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;
    }
}

赫夫曼编码

详见另一篇笔记:

二叉树

详见另一篇笔记:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值