构造哈夫曼树(数据结构实训)(难度系数85)

构造哈夫曼树

题目描述:

根据给定的叶结点字符及其对应的权值创建哈夫曼树。

输入:

第一行为叶子结点的数目n(1<=n<=100)。第二行为一个字符串,包含n个字符,每个字符对应一个叶子结点,第三行为每个叶子结点的概率(即权值),要求根据各叶结点构造哈夫曼树。构造哈夫曼树的原则是先两个最小的,构造一个父结点,其中最小的结点为左孩子,次小的为右孩子,如果两个最小的叶结点相等,则取排在前一个位置的为左孩子。

输出:

哈夫曼树的权值,左孩子,右孩子及其对应的父亲,相邻数据之间用空格隔开;
输入样例:

5

abcde

15 25 15 20 25
输出样例:

15 0 0 6

25 0 0 7

15 0 0 6

20 0 0 7

25 0 0 8

30 1 3 8

45 4 2 9

55 5 6 9

100 7 8 0
构造哈夫曼树方法,即题目所示,分别找到最小的两个叶子结点,组成一个新的叶子结点,最后长度不超过2*n-1

java 复制代码
import java.util.*;

public class Xingyuxingxi {
    public static class jgt {
        int qz, lc, rc, fq, dq;//权值,左孩子,右孩子,父结点,存储当前使用过的权值

        public jgt() {
            this.qz = 0;
            this.lc = 0;
            this.rc = 0;
            this.fq = 0;
            this.dq = 0;
        }
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        String str=sc.next();
        int m=2*n-1;
        jgt [] tree=new jgt[m];
        for (int i = 0; i < n; i++) {
            tree[i]=new jgt();//每次都需要初始化
            tree[i].qz=tree[i].dq=sc.nextInt();//dq中储存的是没有使用过的权值,因为一个结点只能使用一次
        }
        while(n!=m) {//最多只有m的长度
            int min1 = 0,min2 = 0;//最小结点,和第二小结点
            for (int j = 0; j < n; j++) {
                if (tree[min1].dq > tree[j].dq)//如果比当前下标的大,则将当前下标保存下来
                {
                    min1 = j;
                }
            }
            tree[min1].dq=Integer.MAX_VALUE;//如果被使用则赋值一个无限大的数表示已经使用
            for (int j = 0; j < n; j++)
            {
                if(tree[min2].dq>tree[j].dq&&min1!=j)//j不能等于min1因为已经存储了这个最小结点,只能使用一次
                {
                    min2=j;
                }
            }
            tree[n]=new jgt();//初始化,不初始化会空指针异常
            tree[n].qz=tree[n].dq=tree[min1].qz+tree[min2].qz;//当前结点权值为最小的两个结点权值之和
            tree[n].lc=min1+1;//左孩子是最小叶子结点的下标,加1是因为从下标为0开始储存的,题目要求输出的下标是从1开始储存的
            tree[n].rc=min2+1;//右孩子是第二小叶子结点的下标
            tree[min1].fq=tree[min2].fq=n+1;//左孩子和右孩子的父结点都是n+1
            tree[min2].dq=Integer.MAX_VALUE;//如果被使用则赋值一个无限大的数表示已经使用
            n++;//每次会产生一个新的结点
        }
        for (int i = 0; i < m; i++) {
            System.out.println(tree[i].qz+" "+tree[i].lc+" "+tree[i].rc+" "+tree[i].fq);
        }
    }
}

注意:下标从同一个下标开始找时,找到第一个最小值要马上赋值一个很大的数,不然的话,最小叶子结点和第二小叶子结点都会是同一个下标,但是每个值只能用一次

相关推荐
盐水冰3 小时前
【烘焙坊项目】后端搭建(12) - 订单状态定时处理,来单提醒和顾客催单
java·后端·学习
凸头3 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun3141593 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
努力也学不会java4 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
攒了一袋星辰4 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql
小涛不学习4 小时前
Spring Boot 详解(从入门到原理)
java·spring boot·后端
旖-旎4 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan4 小时前
朱梁万有递归元定理,重构《易经》
算法·重构
于先生吖5 小时前
Java框架开发短剧漫剧系统:后台管理与接口开发
java·开发语言
智者知已应修善业5 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机