1、信息论基础实验指导老师:贺正芸 班级:信息工程 081姓名:卢慈荣学号:08401400103湖南工业大学电气与信息工程学院实验一 信道容量的迭代算法程序设计一、实验目的(1)进一步熟悉信道容量的迭代算法;(2)学习如何将复杂的公式转化为程序;(3)掌握 C 语言数值计算程序的设计和调试技术。二、实验要求(1)已知:信源符号个数 r、信宿符号个数 s、信道转移概率矩阵 P。(2)输入:任意的一个信道转移概率矩阵。信源符号个数、信宿符号个数和每个具体的转移概率在运行时从键盘输入。(3)输出:最佳信源分布 P*,信道容量 C。三、信道容量迭代算法1:procedure CHANNEL CAPACI
2、TY(r,s,( )jip2:initialize:信源分布 =1/r,相对误差门限 ,C=ip3:repeat4: 1ijrijpij5: 21ex(log)psjiijjrsjiijjip6:C 221logexp(log)rsjiijj7:until 8:output P*= ,C()irp9:end procedure -四、实验代码/*问题: 初始最大容量的设定 exp 的精确求解 */#include#include#include#include#include#define R 1000#define S 1000#define delta 1e-2#define inf 1e
3、6using namespace std;double P_iR,P_jiSR,Thi_ijRS;double Pre_C,Now_C;int r,s,Num; double _log2(double a) return log(a)/log(2);double _exp(double a)return pow(2.718281828459045 ,a);int eps( double a)if(adelta|a=delta)for(i=0;idelta)P_ii+=P_jiji*_log2(Thi_ijij);P_ii=_exp(P_ii);sum+=P_ii;if(fabs(sum)=de
4、lta) for(i=0;i#include #include struct stringschar *string;struct strings *next;struct strings Fstr, *Fh, *FP;/输出当前集合void outputstr(strings *str)docoutstringnext;while(str);coutb?b:a; inline int MAX(int a, int b) return ab?a:b; #define length_a (strlen(CP)#define length_b (strlen(tempPtr)/判断一个码是否在一个
5、码集合中,在则返回 0,不在返回 1int comparing(strings *st_string,char *code)while(st_string-next)st_string=st_string-next;if(!strcmp(st_string-string,code)return 0;return 1;/判断两个码字是否一个是另一个的前缀,如果是则生成后缀码void houzhui(char *CP,char *tempPtr)if (!strcmp(CP,tempPtr)coutnext=NULL;cp_temp-string=new charabs(length_a-leng
6、th_b)+1; char *longstr;longstr=(length_alength_b ? CP : tempPtr);/将长度长的码赋给 longstr/取出后缀for (int k=MIN(length_a,length_b); kstringk - MIN(length_a,length_b)=longstrk;cp_temp-stringabs(length_a-length_b)=NULL;/判断新生成的后缀码是否已在集合 F 里,不在则加入 F 集合if(comparing(Fh,cp_temp-string)FP-next=cp_temp;FP=FP-next;void
7、 main()/功能提示和程序初始化准备coutstring=new charstrlen(c);strcpy(Ch-string, c);Ch-next=NULL;char f=“F :“;Fh-string=new charstrlen(f);strcpy(Fh-string, f);Fh-next=NULL;/输入待检测码的个数int Cnum;coutCnum;couttempstr; CP-next=new (struct strings);CP=CP-next;CP-string=new charstrlen(tempstr) ;strcpy(CP-string, tempstr)
8、;CP-next = NULL;outputstr(Ch);CP=Ch;while(CP-next-next)CP=CP-next;tempPtr=CP;dotempPtr=tempPtr-next;houzhui(CP-string,tempPtr-string);while(tempPtr-next);outputstr(Fh);struct strings *Fbegin,*Fend;Fend=Fh;while(1)if(Fend = FP)coutnext)CP=CP-next;tempPtr=Fbegin;for(;)tempPtr=tempPtr-next;houzhui(CP-s
9、tring,tempPtr-string);if(tempPtr = Fend)break;outputstr(Fh);/输出 F 集合中全部元素4.输入、输出结果:例 1:输入: 唯一可译码的判断!输入待检测码的个数:5输入待检测码1 :xx2 :xz3 :y4 :zz5 :xyzC :xxxzyzzxyzF :是唯一可译码码组!Press any key to continue实验三 Huffman 编码方案程序设计一、实验目的(1)进一步熟悉 Huffman 编码过程;(2)掌握 C 语言递归程序的设计和调试技术。二、实验要求(1)输入:信源符号个数 r、信源的概率分布 P;(2)输出:
10、每个信源符号对应的 Huffman 编码的码字。三、算法1、从键盘输入组成信源 C 的字符个数 N;2、从键盘输入信源 C 和组成信源的字符所对应的概率数组 P;3、用 函数来对信源进行二进制编码;先对 P 按从大到小Hufman进行排序,与此同时要把 C 中相应的字符的位置做相应的调换;用数组来记录编码:在进行记录编码时是从数组 的最后一个cont count开始存储的,而且,每进行一次编码所记录下来的两个编码 是1,0按从数组的最后一个元素开始服从 countm-k-j、countm-k-j-1,其中 k 表示编码所进行的次数,j 表示每次编码都只有 ;最后用函数,来输出编码。int()p
11、r四、代码#include #include #include int m,s1,s2; typedef struct unsigned int weight; unsigned int parent,lchild,rchild; HTNode,*HuffmanTree; /动态分配数组存储哈夫曼树 typedef char *HuffmanCode; /动态分配数组存储哈夫曼编码表 void Select(HuffmanTree HT,int n) int i,j; for(i = 1;i HTi.weight) for(j = 1;j HTj.weight) void HuffmanCod
12、ing(HuffmanTree char *cd; int p; int cdlen; if (n=1) return; m = 2 * n - 1; HT = (HuffmanTree)malloc(m+1) * sizeof(HTNode); / 0 号单元未用 for (i=1; i=n; i+) /初始化 HTi.weight=wi-1; HTi.parent=0; HTi.lchild=0; HTi.rchild=0; for (i=n+1; i=m; i+) /初始化 HTi.weight=0; HTi.parent=0; HTi.lchild=0; HTi.rchild=0; p
13、uts(“n 哈夫曼树的构造过程如下所示:“); printf(“HT 初态:n 结点 weight parent lchild rchild“); for (i=1; i=m; i+) printf(“n%4d%8d%8d%8d%8d“,i,HTi.weight, HTi.parent,HTi.lchild, HTi.rchild); printf(“ 按任意键,继续 .“); getchar(); for (i=n+1; i=m; i+) / 建哈夫曼树 / 在 HT1i-1中选择 parent 为 0 且 weight 最小的两个结点, / 其序号分别为 s1 和 s2。 Select(
14、HT, i-1); HTs1.parent = i; HTs2.parent = i; HTi.lchild = s1; HTi.rchild = s2; HTi.weight = HTs1.weight + HTs2.weight; printf(“nselect: s1=%d s2=%dn“, s1, s2); printf(“ 结点 weight parent lchild rchild“); for (j=1; j=i; j+) printf(“n%4d%8d%8d%8d%8d“,j,HTj.weight, HTj.parent,HTj.lchild, HTj.rchild); pri
15、ntf(“ 按任意键,继续 .“); getchar(); /-无栈非递归遍历哈夫曼树,求哈夫曼编码 cd = (char *)malloc(n*sizeof(char); / 分配求编码的工作空间 p = m; cdlen = 0; for (i=1; i=m; +i) / 遍历哈夫曼树时用作结点状态标志 HTi.weight = 0; while (p) if (HTp.weight=0) / 向左 HTp.weight = 1; if (HTp.lchild != 0) p = HTp.lchild; cdcdlen+ =0; else if (HTp.rchild = 0) / 登记叶
16、子结点的字符的编码 HCp = (char *)malloc(cdlen+1) * sizeof(char); cdcdlen =0; strcpy(HCp, cd); / 复制编码 (串) else if (HTp.weight=1) / 向右 HTp.weight = 2; if (HTp.rchild != 0) p = HTp.rchild; cdcdlen+ =1; else / HTp.weight=2,退回退到父结点,编码长度减 1 HTp.weight = 0; p = HTp.parent; -cdlen; / HuffmanCoding void main() Huffma
17、nTree HT;HuffmanCode *HC;int *w,n,i; puts(“输入结点数:“); scanf(“%d“, HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode); w = (int *)malloc(n*sizeof(int); printf(“输入 %d 个结点的权值n“,n); for(i = 0;i n;i+) scanf(“%d“, HuffmanCoding(HT,HC,w,n); puts(“n 各结点的哈夫曼编码:“); for(i = 1;i = n;i+) printf(“%2d(%4d):%sn“,i,wi-1,HCi); getchar(); 四、运行结果输入节点数 5五个节点权值:51 23 21 3 75五、实验总结本实验使用 c 语言编写,用 Huffman 函数来对信源进行二进制编码,由于对 Huffman 比较熟悉,编写起来也比较简单,程序先对 P 按从大到小进行排序,与此同时要把 C 中相应的字符的位置做相应的调换,本实验很好的复习了 Huffman 的内容,对于信息论与编码的巩固也有很大的好处,同时也是对 C 使用技巧的提高。