问题:给定字符集C={x1,x2,…,xn}和每个字符的频率f(xi),求关于C的一个最优前缀码。
-
解析
-
设计
void CharSetHuffmanEncoding(HuffmanTree T, HuffmanCode H) {
//根据哈夫曼树T求哈夫曼编码表H
int c, p;//c和p分别指示T中孩子和双亲的位置
char cd[n + 1];//临时存放编码
int start;//指示编码在cd中的起始位置
cd[n] = '\0';//编码结束符
getchar();
for (int i = 0; i < n; i++) {//依次求叶子T[i]的编码
H[i].ch = getchar();//读入叶子T[i]对应的字符
start = n;//编码起始位置的初值
c = i;//从叶子T[i]开始上溯
while ((p = T[c].parent) >= 0) {//直至上溯到T[c]是树根为止
//若T[c]是T[p]的左孩子,则生成代码0;否则生成代码1
if (T[p].left == c)
cd[--start] = '0';
else
cd[--start] = '1';
c = p;//继续上溯
}
strcpy(H[i].bits, &cd[start]);//复制编码位串
}
}
-
分析
O(nlogn)频率排序;for循环O(n),插入操作O(logn),算法时间复杂度是O(nlogn) -
源码
#include <iostream>
#include <cstdio>
#include <fstream>
using namespace std;
int n, m; //n个顶点 m种颜色
int a = 1, b = 1; //输入时的顶点
int count = 0; //记录总方案数
int graph[20][20] = {0}; //记录无向图
int color[20] = {0}; //颜色
bool ok(int c) //判断是否可以涂上该颜色
{
for(int k = 1; k <= n; k++)
{
if(graph[c][k] && color[c] == color[k]){
return false;
}
}
return true;
}
void backtrack(int cur) //回溯的过程
{
if(cur > n){
for(int i = 1; i <= n; i++){
printf("%d ",color[i]);
}
count++;
printf("\n");
}else{
for(int i = 1; i <= m; i++)
{
color[cur] = i;
if(ok(cur)){
backtrack(cur + 1);
}
color[cur] = 0;
}
}
}
int main()
{
ifstream fin("input.txt");
fin >> n >> m;
// cin >> n >> m;
cout << "输入的无向图为:" << endl;
while(fin >> a >> b && a != 0 && b != 0){
cout << a << " " << b << endl;
graph[a][b] = 1;
graph[b][a] = 1; //无向图记录两边
}
cout << "*******************" << endl;
backtrack(1);
cout << "总共的方案数为:" << endl;
cout << count << endl;
system("pause");
return 0;
}