算法分析设计实践——哈夫曼编码
问题:
设需要编码的字符集为{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