1、电子科技大学电子工程学院 信息论课程设计报告 课程名称:信息编码与加密 课 程 设 计 报 告 学生姓名:农瀚 学号: 指引教师:李万春 一、课程设计名称:编程实现霍夫曼、费诺、香农编码 二、课设原理: 1)霍夫曼编码:霍夫曼编码平均码长最短,是最佳编码。编码环节如下: (1)将信源符号按概率大小排序; (2)对概率最小两个符号求其概率之和,同步给两幅 号分别赋予码元0和1; (3) 将概率之和当做一种新符号概率。与剩余概率
2、 一起,形成一种缩减信源,再重复上述环节,直到概率和为1为止; (4) 按上述环节事实上构成了一种码树,从根到端点通过树枝即为码字。 2)费诺编码: 编码环节如下: (1) 将信源概率从大到小排序; (2) 将信源符号提成两组,使两组信源符号概率之和近似相等,并给两组信源符号分别赋0和1; (3) 再把各个小组信源符号细分为两组并赋码元,办法与第一次分组相似; (4) 如此始终下去,直到每一种小组只含一种信源符号为止; (5) 由此可构导致一种码树,所有终端节点上码字构成费诺码。 3)香农编码: 编码办法如下: ⑴ 将信
3、源消息符号按其浮现概率大小依次排列 p(u1)≥p(u2)≥…≥ p(un) ⑵ 拟定码长Ki (整数) : Ki= []——取整 ⑶ 为了编成唯一可译码,计算第i个消息累加概率 ⑷ 将累加概率Pi变换成二进制数。 ⑸ 取pi二进制数小数点后Ki位即为该消息符号二进制数。 三、课设目:通过编程实现三种方式编码,掌握三种编 码方式环节。 四、课设内容: 三种编码方式编程思路: 1、霍夫曼编码:(1)对给定n个权值{W1,W2,W3,...,Wi,...,Wn}构
4、成n棵二叉树初始集合F= {T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一种权值为Wi根结点,它左右子树均为空。(为以便在计算机上实现算 法,普通还规定以Ti权值Wi升序排列。) (2)在F中选用两棵根结点权值最小树作为新构造二叉树左右子树,新二叉树根结点权值为其左右子树根结点权值之和。 (3)从F中删除这两棵树,并把这棵新二叉树同样以升序排列加入到集合F中。 (4)重复二和三两步,直到集合F中只有一棵二叉树为止。 2、费诺编码编程思路:(1)先使用冒泡法对信源概率概率排序; (2)依次将按排好序符号概率进行近似1:1提成两大组; (3)对各组赋予一种二
5、进制码元“0”和“1”; (4)输出符号,符号概率及编码。 3、香农编码: (1)对于一种给定符号列表,制定了概率相应列表或频率计数,使每个符号相对发生频率是已知。 (2)排序依照频率符号列表,最常浮现符号在左边,至少浮现符号在右边。 (3)清单分为两某些,使左边某些总频率和尽量接近右边某些总频率和。 (4)该列表左半边分派二进制数字0,右半边是分派数字1。这意味着,在第一半符号代都是将所有从0开始,第二半代码都从1开始。 (5)对左、右半某些递归应用环节3和4,细分群体,并添加位代码,直到每个符号已成为一种相应代码树叶。 五、器材(设备、元器件): 计算机、visu
6、al studio社区版 六、设计代码:见附录 九、实验数据及成果 依照上述实验程序得到实验数据及成果如下: 霍夫曼编码: 费诺编码: 香农编码: 十、结论 完毕了20个非等概随机信源霍夫曼、费诺和香农编码,并给出了编码效率和码字。 十一、总结及心得体会 通过这次课程设计,我掌握了三种编码方式环节,并可以运用编程实现编码,提高了自己编程水平和对该知识点掌握限度。 附录代码: // ConsoleApplication1.cpp :定义控制台应用程序入口点。 // /*******霍夫曼编码
7、/
#include "stdafx.h"
#include
8、2 -1 double Sp[SourNum]; char coder[100][100]; int bitlong[100]; void ProSource()//产生非等概信源函数 { int n = 0; srand((unsigned)time(0)); double sum = 0; while (1) { Sp[n] = (double)rand() / (RAND_MAX);//产生随机浮点数 sum = sum + Sp[n]; if (sum < 1 && Sp[n] <0.086) { n++;
9、 if (n >19) break; else continue; } else { sum = sum - Sp[n]; Sp[n] = 0; continue; } } Sp[SourNum] = 1 - sum; } /*******霍夫曼编码*************/ typedef struct { int bit[MAXBIT]; int start; } HCode; typedef struct { double weight; double pare
10、nt; double lchild; double rchild; int last; } HNodeType; void HuffmanTree(HNodeType HuffNode[MAXNODE],int n) { int i,j,x1,x2;; double m1,m2; for (i = 0;i < 2 * n - 1;i++) { HuffNode[i].weight = 0; HuffNode[i].parent = -1; HuffNode[i].lchild = -1; HuffNode[i].rchi
11、ld = -1; } for (i = 0;i < n;i++) { HuffNode[i].weight = Sp[i]; } for (i = 0;i < n - 1;i++) { m1 = m2 = MaxValue; x1 = x2 = 0; for (j = 0;j < n + i;j++) { if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1) { m2 = m1; x2 = x1; m1 = HuffNo
12、de[j].weight; x1 = j; } else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1) { m2 = HuffNode[j].weight; x2 = j; } } HuffNode[x1].parent = n + i; HuffNode[x2].parent = n + i; HuffNode[n + i].weight = HuffNode[x1].weight + HuffNode[x2].weight; Huf
13、fNode[n + i].lchild = x1; HuffNode[n + i].rchild = x2; } } double CodEffi()//求编码效率 { int AveraLong = 0,SumLong = 0; double H = 0,CE = 0; for (int i = 0;i < SourNum;i++) { SumLong = SumLong + bitlong[i]; } AveraLong = SumLong / SourNum; for (int j = 0;j < SourNum;j++) {
14、H = (-Sp[j])*(log(Sp[j]) / log(2)) + H; } CE = H / AveraLong; return CE; } int main() { ProSource(); sort(Sp,Sp + SourNum); HNodeType HuffNode[MAXNODE]; HCode HuffCode[MAXLEAF],cd; int i,j,c,p,n; n = SourNum; HuffmanTree(HuffNode,SourNum + 1); for (i = 0;i < n;i++) { cd
15、start = n - 1;
c = i;
p = HuffNode[c].parent;
while (p != -1)
{
if (HuffNode[p].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
c = p;
p = HuffNode[c].parent;
}
for (j = cd.start + 1;j 16、bit[j];
}
HuffCode[i].start = cd.start;
}
memset(coder,'\0',sizeof(coder));
int temp=0;
for (i = 0;i 17、);
temp++;
}
temp = 0;
cout << " 信源概率:" << Sp[i];
cout << " 字长:" << strlen(coder[i]);
printf("\n");
bitlong[i] = strlen(coder[i]);
}
CodEffi();
cout << "\n编码效率: " << CodEffi() * 100 << "%\n";
return 0;
}
// 费诺编码.cpp :定义控制台应用程序入口点。
//
#include "stdafx.h" 18、
#include 19、00];
void group1(int low,int mid,int high);
void code(int low,int mid,int high);
void ProSource()//产生非等概信源函数
{
int n = 0;
srand((unsigned)time(0));
double sum = 0;
while (1)
{
Sp[n] = (double)rand() / (RAND_MAX);//产生随机浮点数
sum = sum + Sp[n];
if (sum < 1 && Sp[n] <0.086) //
20、 {
n++;
if (n >19)
break;
else continue;
}
else
{
sum = sum - Sp[n];
Sp[n] = 0;
continue;
}
}
Sp[SourNum] = 1 - sum;
}
struct Bit
{
char b[Bmax]; //定义码长度数组数据类型 字符型 构成成员
int last;
};
typedef struct symbol 21、
{
int c;
double probability;
struct Bit bit;
}sbl;
sbl s[Smax];
/********输入符号符号概率***** 22、/
void input(int n)
{
int i;
int c;
for (i = 0;i 23、/
void code(int low,int mid,int high)
{
int i;
for (i = low;i 24、
s[i].bit.last++;
}
else
{
s[i].bit.b[s[i].bit.last] = '1';
s[i].bit.last++;
}
}
}
void sort(int n)
{
double t;
char a;
int i 25、j;
for (i = 1;i 26、 + 1].probability;
s[j].c = s[j + 1].c;
s[j + 1].probability = t;
s[j + 1].c = a;
}
}
/************分组函数************/
void group(int n)
{
int i,pmid,plow,phigh;
pmid = phig 27、h = n;
plow = 0;
for (i = 0;i 28、
}
void group1(int low,int mid,int high)
{
double d,dmin;
d = 0;
int i;
if (high == low + 1) 29、
return;
for (i = low;i 30、 - 2 * s[i].probability);
if (d 31、
group1(mid,high,high);
}
void output(int n)
{
int i,j;
printf("费诺编码输出信源,概率及编码:\n\n");
for (i = 0;i 32、"信源:"< 33、ong =0,SumLong=0;
double H=0,CE=0;
for (int i = 0;i < SourNum;i++)
{
SumLong = SumLong + bitlong[i];
}
AveraLong = SumLong / SourNum;
for (int j=0;j < SourNum;j++)
{
H = (-Sp[j])*(log(Sp[j]) / log(2)) + H;
}
CE = H / AveraLong;
return CE;
}
void main() 34、 //主函数
{
int n = SourNum; //定义变量
ProSource();
input(n); //分别调用输入、排序、分组、输出函数,并执行
sort(n);
group(n);
output(n);
cout << "\n编码效率: " << CodEffi() * 100 35、<< "%\n";
}
// 香农编码.cpp :定义控制台应用程序入口点。
//
#include "stdafx.h"
#include 36、define Smax 20
using namespace std;
#define SourNum 20
double Sp[SourNum];
int bitlong[100];
struct shan
{
int s;
double p;
double padd;
double l_f;
int l;
char w[20];
};
shan SourData[SourNum];
void group1(int low,int mid,int high);
void code(int low,int mid,int high); 37、
void ProSource()//产生非等概信源函数
{
int n = 0;
srand((unsigned)time(0));
double sum = 0;
while (1)
{
Sp[n] = (double)rand() / (RAND_MAX);//产生随机浮点数
sum = sum + Sp[n];
if (sum < 1 && Sp[n] <0.086) //
{
n++;
if (n >19)
break;
else continue;
}
else
{
38、sum = sum - Sp[n];
Sp[n] = 0;
continue;
}
}
Sp[SourNum] = 1 - sum;
}
int i,j,n,k,b;
double addp;
char bitw[20];
void sequ(struct shan x[],int n)
{
struct shan temp;
for (i = 0;i 39、j] = x[i];
x[i] = temp;
}
}
}
void countpadd(struct shan x[],int n)
{
addp = 0;
x[0].padd = 0;
for (i = 0;i 40、f ((x[i].l_f - (int)x[i].l_f)>0)
x[i].l = (int)x[i].l_f + 1;
else x[i].l = (int)x[i].l_f;
}
}
void covbit(double a,int lc)
{
for (j = 0;j 41、le H = 0,CE = 0;
for (int i = 0;i < SourNum;i++)
{
SumLong = SumLong + bitlong[i];
}
AveraLong = SumLong / SourNum;
for (int j = 0;j < SourNum;j++)
{
H = (-Sp[j])*(log(Sp[j]) / log(2)) + H;
}
CE = H / AveraLong;
return CE;
}
int main()
{
n = SourNum;
ProSource();
for 42、 (i = 0;i 43、输出数据*/
cout.fill(' ');
for (i = 0;i






