• 算法分析与设计(work11)


    1、问题

    给定字符集 (C ={x_{1},x_{2},...,x_{n}}) 和每个字符的频率 (f(x_{i})) ,求关于C的 一个最优前缀码?

    2、解析

    构造一个最优前缀码的贪心方法就是哈夫曼算法(Huffman)。
    因为二元前缀编码的储存就是就是二叉树结构,每个字符作为树叶,对应这个字符的前缀码看作根到这片树叶的一条路径,每个结点通向左二子的边记作 0,通向右儿子的边记作 1.
    那么这个问题我们可以进行一下转化,问题就是构造一颗带权的二叉树,使得各个叶子节点x的深度乘以出现的频率f(x) 之和最小。
    很显然考虑贪心算法,即让出现频率高的字符位于的深度尽量小。
    算法过程:
    频率表:A:60    B: 45   D: 20 E:3 F: 5
    1、从小到大排序:E F D B A
    2、

    通过上述方法构造出来的树即哈夫曼树。

    3、设计

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef struct
    {
        int weight;
        char ch;
        int parent;
        int leftchild;
        int rightchild;	
    }Huffman;
    
    typedef struct Hcode
    {
        int code[100]; 
        int start;           
    };
    
    Huffman huffman[100];
    Hcode code[100];
    
    void HuffmanTree(int n)
    {
    	int a,b,c,d;
        for (int i=0;i<n*2-1;++i)
    	{
            huffman[i].weight=0;
            huffman[i].parent=-1;
            huffman[i].leftchild=-1;
            huffman[i].rightchild=-1;
        }
        for (int i=0;i<n;i++)
    	{
            cin >> huffman[i].ch;
            scanf("%d",&huffman[i].weight);
        }
        for (int i=0;i<n-1;i++)
    	{
            a=b=-1;
            c=d=10000;
            for (int j=0;j<n+i;j++)
    		{
                if (huffman[j].parent==-1 && huffman[j].weight<c)
    			{
                    d=c;
                    b=a;
                    a=j;
                    c=huffman[j].weight;
                }
                else if (huffman[j].parent==-1 && huffman[j].weight<d)
    			{
                    b=j;
                    d=huffman[j].weight;
                }
            }
            huffman[n+i].leftchild=a;
            huffman[n+i].rightchild=b;
            huffman[n+i].weight=c+d;
            huffman[a].parent=n+i;
            huffman[b].parent=n+i;
        }
    }
    void printHuffmanTree(int n)
    {
        Hcode tcode;
        int curParent;
        int c;
        for (int i = 0; i < n; ++i){
            tcode.start = n - 1;
            c = i;
            curParent = huffman[i].parent;
            while (curParent != -1)
    		{
                if (huffman[curParent].leftchild == c)
    			{
                    tcode.code[tcode.start] = 0;
                }
                else
    			{
                    tcode.code[tcode.start] = 1;
                }
                tcode.start--;
                c=curParent;
                curParent=huffman[c].parent;
            }
            for(int j=tcode.start+1;j<n;j++)
    		{
                code[i].code[j] = tcode.code[j];
            }
            code[i].start = tcode.start;
        }
    }
    int main()
    {
    	int n=0;
        scanf("%d",&n);
        HuffmanTree(n);
        printHuffmanTree(n);
        for (int i=0;i<n;++i)
    	{
            printf("%c :",huffman[i].ch);
            for (int j=code[i].start+1;j<n;++j)
    		{
                printf("%d",code[i].code[j]);
            }
            printf("
    ");
        }
        return 0;
    }
    

    4、分析

    排序: (O(nlogn)) ,对于树的遍历: (O(nlogn)) ,总时间复杂度: (O(nlogn))

    5、源码

    https://github.com/HaHe-a/Algorithm-analysis-and-design-code/blob/master/huffman.cpp

    越自律,越自由
  • 相关阅读:
    node.js之Cookie
    jQuery和js之Cookie实现
    StringRedisTemplate操作Redis
    Could not get a resource from the pool 错误解决
    tableLayoutPanel 列宽度设置
    KRBTabControl(中文)Windows选项卡控件
    KRBTabControl
    Deferred content load was not performed. To provide the content, subscribe to the View's QueryControl event
    where(泛型类型约束)
    ExportAsFixedFormat Visio文件另存为其他几种格式的处理
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14818675.html
Copyright © 2020-2023  润新知