算法分析设计实践——哈夫曼编码

问题:

设需要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最短的不等长编码方案。

解析:

实数w1,w2,···,wt且 w1<=w2<=···<=wt           

(1)连接w1,w2为权的两片树叶,得一分支点,其权为w1+w2 ;

(2)在w1+w2, w3+···+wt中选出两个最小的权,连接它们对应的顶点(不一定都是树叶),得分支点及所带的权;

(3)重复(2),直到形成t – 1个分支点,t片树叶为止。

构建好哈夫曼树之后,哈夫曼树的左边分支置为0,右边分支置为1,就可以形成每个字母的不等长编码。

设计:

void SetHuffTree(node HuffTree[],int w[] , char ch[], int n)
{
    for (int i = 0; i < 2 * n - 1; ++i)
    {
        HuffTree[i].parent = -1;
        HuffTree[i].lchild = -1;
        HuffTree[i].rchild = -1;
    }
    for (int i = 0; i < n; ++i)
    {
        HuffTree[i].weight = w[i];
        HuffTree[i].ch = ch[i];
    }
    for (int i = n; i < 2 * n - 1; ++i)
    {
        int a = 0, b = 0;
        select(HuffTree, &a, &b, i);
        HuffTree[a].parent = i;
        HuffTree[b].parent = i;
        HuffTree[i].weight = HuffTree[a].weight + HuffTree[b].weight;
        HuffTree[i].lchild = a;
        HuffTree[i].rchild = b;
    }

}

分析:

时间复杂度:O(n * n)

源码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<cctype>
#include<time.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid + 1,r
#define P pair<int,int>
#define ull unsigned long long
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const ll mod = 998244353;
const int inf = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-7;

int n;
struct node
{
    int weight;
    char ch;
    int lchild, rchild, parent;
}HuffTree[maxn * 2];

int w[maxn];
char ch[maxn];
void select(node HuffTree[], int* a, int *b ,  int n)
{
    int weight = inf;
    for (int i = 0; i < n; ++i)
    {
        if (HuffTree[i].parent != -1)
            continue;
        else
        {
            if (HuffTree[i].weight < weight)
            {
                weight = HuffTree[i].weight;
                *a = i;
            }
        }
    }
    weight = inf;
    for (int i = 0; i < n; ++i)
    {
        if (HuffTree[i].parent != -1 || i == *a)
            continue;
        else
        {
            if (HuffTree[i].weight < weight)
            {
                weight = HuffTree[i].weight;
                *b = i;
            }
        }
    }
    int temp;
    if (HuffTree[*a].lchild < HuffTree[*b].lchild)
    {
        temp = *a;
        *a = *b;
        *b = temp;
        //swap(*a, *b);
    }
}


void SetHuffTree(node HuffTree[],int w[] , char ch[], int n)
{
    for (int i = 0; i < 2 * n - 1; ++i)
    {
        HuffTree[i].parent = -1;
        HuffTree[i].lchild = -1;
        HuffTree[i].rchild = -1;
    }
    for (int i = 0; i < n; ++i)
    {
        HuffTree[i].weight = w[i];
        HuffTree[i].ch = ch[i];
    }
    for (int i = n; i < 2 * n - 1; ++i)
    {
        int a = 0, b = 0;
        select(HuffTree, &a, &b, i);
        HuffTree[a].parent = i;
        HuffTree[b].parent = i;
        HuffTree[i].weight = HuffTree[a].weight + HuffTree[b].weight;
        HuffTree[i].lchild = a;
        HuffTree[i].rchild = b;
    }

}


void SetHuffCode(node HuffTree[], int n)
{
    string s = "";
    for (int i = 0; i < n; ++i)
    {
        s = "";
        int j = i;
        while (HuffTree[j].parent != -1)
        {
            int k = HuffTree[j].parent;
            if (j == HuffTree[k].lchild)
            {
                s += "0";
            }
            else
            {
                s += "1";
            }
            j = HuffTree[j].parent;
        }
        cout << "字符" << HuffTree[i].ch << "的编码" << endl;
        for (int i = s.size() - 1; i >= 0; --i)
        {
            cout << s.at(i);
        }
        cout << endl;
    }
}

int main()
{
    scanf("%d", &n);
    scanf("%s", ch);
    for (int i = 0; i < n; ++i)
    {
        scanf("%d", &w[i]);
    }
    
    SetHuffTree(HuffTree, w, ch , n);
    SetHuffCode(HuffTree, n);
    return 0;
}
完整代码

https://github.com/BambooCertain/Algorithm.git

 

posted @ 2020-05-19 23:45  当然是斗笠呀  阅读(770)  评论(0编辑  收藏  举报