zoukankan      html  css  js  c++  java
  • 5678: 数据结构实验:哈夫曼树和编码

    描述

    当用 n 个结点(都做叶子结点且都有各自的权值)试图构建一棵树时,如果构建的这棵树的带权路径长度最小,称这棵树为“最优二叉树”,有时也叫“赫夫曼树”或者“哈夫曼树”。

    现给定若干权值,请构建一棵哈夫曼树,并输出各个权值对应的哈夫曼编码长度。

    哈夫曼树中的结点定义如下:

    //哈夫曼树结点结构

    typedef struct

    {

        int weight;//结点权重

        int parent, left, right;//父结点、左孩子、右孩子在数组中的位置下标

    }HTNode, *HuffmanTree;

    //动态二维数组,存储哈夫曼编码

    typedef char ** HuffmanCode;

    部分代码已完成,请补充完整,提交时请勿包含给定代码。

    //打印哈夫曼编码的函数
    void PrintHuffmanCode(HuffmanCode htable, int *w, int n)
    {
        printf("Huffman code:
    ");
        for(int i = 1; i <= n; i++)
            printf("%d(%d)
    ",w[i-1], strlen(htable[i]));
    }
    int main()
    {
        int w[100], n, i;
        scanf("%d", &n);
        for(i=0;i<n;i++)
            scanf("%d", &w[i]);
        HuffmanTree htree;
        HuffmanCode htable;
        CreateHuffmanTree(htree, w, n);
        HuffmanCoding(htree, htable, n);
        PrintHuffmanCode(htable,w, n);
        return 0;
    }

    输入

    输入数据第一行为n(不超过100),接下来有n个正整数,表示权值。

    输出

    按照输入权值顺序输出相应的哈夫曼编码的长度,格式见样例。

    样例输入

    样例输出

    代码:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 typedef struct
      5 {
      6     int weight;//结点权重
      7     int parent, left, right;//父结点、左孩子、右孩子在数组中的位置下标
      8 }HTNode, *HuffmanTree;
      9 typedef char ** HuffmanCode;
     10 
     11 void select(HuffmanTree htree,int n, int *s1,int *s2){
     12     int minn;
     13     for(int i=1;i<=n;i++){
     14         if((htree)[i].parent==0){ //如果此结点的父亲没有,那么把结点号赋值给 min,跳出循环
     15             minn=i;
     16             break;
     17         }
     18     }
     19     for(int i=1;i<=n;i++){   //找出权值最小的
     20         if((htree)[i].parent==0){
     21             if((htree)[i].weight<(htree)[minn].weight){
     22                 minn=i;
     23             }
     24         }
     25     }
     26     *s1=minn;  //编号
     27     for(int i=1;i<=n;i++){
     28         if((htree)[i].parent==0&&i!=(*s1)){ //如果此结点的父亲没有,那么把结点号赋值给 min,跳出循环
     29             minn=i;
     30             break;
     31         }
     32     }
     33     for(int i=1;i<=n;i++){
     34         if((htree)[i].parent==0&&i!=(*s1)){
     35             if((htree)[i].weight<(htree)[minn].weight){
     36                 minn=i;
     37             }
     38         }
     39     }
     40     *s2=minn;   //找出两个编号最小的
     41 }
     42 
     43 void CreateHuffmanTree(HuffmanTree &htree,int w[],int n){
     44     if(n<=1) return; // 如果只有一个编码就相当于 0
     45     int m=2*n-1;  //哈夫曼树度为2或为0 总结点树为2*n-1;
     46     int s1,s2; //s1 和 s2 为两个当前结点里,要选取的最小权值的结点
     47     htree=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
     48     for(int i=1;i<=n;i++){     //1--n号存放叶子结点,初始化叶子结点,结构数组来初始化每个叶子结点
     49         (htree)[i].weight=w[i-1];
     50         (htree)[i].parent=0;
     51         (htree)[i].left=0;
     52         (htree)[i].right=0;
     53     }
     54     for(int i=n+1;i<=m;i++){  //非叶子结点的初始化
     55         (htree)[i].weight=0;
     56         (htree)[i].parent=0;
     57         (htree)[i].left=0;
     58         (htree)[i].right=0;
     59     }
     60     for(int i=n+1;i<=m;i++){   //创建非叶子结点,建哈夫曼树
     61         select(htree, i-1, &s1, &s2);  //再前面有权值里面选出两个最小的构建二叉树
     62         (htree)[s1].parent=i;
     63         (htree)[s2].parent=i;
     64         (htree)[i].left=s1;
     65         (htree)[i].right=s2;
     66         (htree)[i].weight=(htree)[s1].weight+(htree)[s2].weight;
     67     }
     68 }
     69 
     70 void HuffmanCoding(HuffmanTree &htree,HuffmanCode &htable,int n){
     71     htable=(HuffmanCode)malloc((n+1)*sizeof(char*));
     72     char *cd = (char *)malloc(n*sizeof(char));
     73     cd[n-1]='';
     74     for(int i=1;i<=n;i++){   //从叶子节点开始
     75         //从叶子结点出发,得到的哈夫曼编码是逆序的,需要在字符串数组中逆序存放
     76         int start=n-1;
     77         int c=i;
     78         int j=htree[i].parent;
     79         while(j!=0){
     80             // 如果该结点是父结点的左孩子则对应路径编码为 0,否则为右孩子编码为 1
     81             if(htree[j].left==c){
     82                 cd[--start]='0';
     83             }
     84             else cd[--start]='1';
     85             c=j;
     86             j=htree[j].parent;
     87         }
     88         //跳出循环后,cd 数组中从下标 start 开始,存放的就是该结点的哈夫曼编码
     89         htable[i] = (char *)malloc((n-start)*sizeof(char));
     90         strcpy(htable[i],&cd[start]);
     91     }
     92     free(cd);
     93 }
     94 
     95 void PrintHuffmanCode(HuffmanCode htable, int *w, int n)
     96 {
     97     printf("Huffman code:
    ");
     98     for(int i = 1; i <= n; i++)
     99         printf("%d(%d)
    ",w[i-1], strlen(htable[i]));
    100 }
    101 
    102 int main()
    103 {
    104     int w[100], n, i;
    105     scanf("%d", &n);
    106     for(i=0;i<n;i++)
    107         scanf("%d", &w[i]);
    108     HuffmanTree htree;
    109     HuffmanCode htable;
    110     CreateHuffmanTree(htree, w, n);
    111     HuffmanCoding(htree, htable, n);
    112     PrintHuffmanCode(htable,w, n);
    113     return 0;
    114 }
    View Code
  • 相关阅读:
    go标准库的学习-net/http
    go标准库的学习-sync互斥
    sqlplus命令大全
    Oracle 11g安装步骤详谈
    安装64位版Oracle11gR2后无法启动SQLDeveloper的解决方案(原创) (2016-10-29 下午01:56)
    Dos命令查看端口占用及关闭进程
    access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
    Hibernate的集合映射与sort、order-by属性
    Hibernate总结2 API和配置文件
    MyEclipse8.5启动无法选择工作空间的问题
  • 原文地址:https://www.cnblogs.com/qq-1585047819/p/10841113.html
Copyright © 2011-2022 走看看