哈夫曼树及其应用笔记(待完善)

1.哈夫曼树

  •          几个基本概念:路径 路径长度...
  •         什么样的树路径长度(PL)最小?完全二叉树。
  •         什么样的树带权路径长度(WPL)最小?哈夫曼树。
  •         n0 = n2+1,n0+n2 = 2n0-1=n(n0叶子节点,n2非叶子节点,n总叶子节点)
  •         哈夫曼树构造算法               
    /************算法思路******************/
    //总节点多少?(记为n)             
    //初始化这些节点(叶子节点置权值x000 for(i:1~n0)剩余的置0000 for(i:~n))               
    //找到两个parent为0,并且权值最小的节点。    for(i:n+1~m)                
    //把这两个节点的父节点(序号i)置一下,父节点(ht[i])的左右孩子置一下,再置父节点的权值。
    
    /******************************具体代码*************************/
    
    void create_hafumantree(hafumantree ht,int n0,int w[]){
    //给出参数 叶子节点权值,叶子节点数
         n = 2*n0-1;
    //i是序号 p是数组,初始化这些节点
         for(p = ht,i = 1;i<=n0;i++,p++,w++) *p = {*w,0,0,0};  //?
         for(;i<=n;i++,p++) *p = {0,0,0,0};
    //在i-1的范围里找双亲节点为0且权值最小的两点s1 s2
         for(i=n+1;i<=m;i++){
             select(ht,i-1,&s1,&s2);
             ht[s1].parent = i;
             ht[s2].parent = i;
             ht[i].Lchild = s1;
             ht[i].Rchild = s2;
             ht[i].weight = ht[s1].weight+ht[s2].weight;
    }
    ...
    }

2.哈夫曼树应用(哈夫曼编码)

 

  • 定理1:前缀码
  • 定理2:哈夫曼编码是前缀码,是最短、最优前缀码(使带权路径最小)
  • 哈夫曼编码算法
    /************算法思路***************/
    //申请n个字符指针,每个字符指针指向一个数组(竖着给空间hc)
    //申请cd辅助存储单元,可以放n个字符,最后一位给一个'/0'表结束 (以上准备工作)(横着给空间cd)
    //for(i:0~n-1) hc[i] = cd; 
    /*PS:
        求cd(叶子节点编码)(横着)
        start指针指向cd最后一位
        for(c->child = i,f->c双亲节点 = ht[i].parent;f!=0;c = f,f = ht[f].parent)(横着)
            如果是左孩子就置0,否则置1
            start指针往前退一位   */      (求哈夫曼码(每个倒着填数))
    
    //(竖着给空间hc)(横着给空间cd)
    //(求哈夫曼码(倒着填数))
    /*****************具体代码***************/
    //从叶子节点到根   逆向求每个字符或者指令的   哈夫曼编码
    //参数:给出ht(哈夫曼树),n0(叶子节点个数),求hc
    
    void CreateHaffmanCode(HaffmanTree ht,HaffmanCode hc,int n0){
        hc = (hafumannode)malloc(n0*sizeof(char*));
        cd = (char*)malloc(n0*sizeof(char));    //?
        cd[n0-1] = '\0';
    
    /*hc = new char*[n0+1];
    cd = new char[n0];*/
    
        for(int i = 0;i<n;i++){
            start = n0-1;
            for(c = i,f = ht[c].parent;f!=0;c = f,f = ht[f].parent)
                if(ht[c].Lchild == c) cd[--start]='0';
                else cd[--start] = '1';
    
            hc[i] = (char*)malloc(n-start)*sizeof(char)); //?
            strcpy(hc[i],&cd[start]);
    
    /*nc[i] = new char[n-start];*/
    }
        free(cd);
    }

//指针学的差,关于c的基本知识有所缺漏。无法完全理解。以下另一种较好理解方式。

//给出要构造的哈夫曼树和叶子节点个数
//总节点个数,初始化节点
//找到权值最小节点,认父母,变权值 
void CreateHaffmanTree(haffmantree ht,int n0){
    if(n<=1) return;
	int n = 2*n0-1;
	ht = new HTNode[n+1];
	for(int i = 1;i<=n;i++){
		ht[i].parent = 0;
		ht[i].lchild = 0;
		ht[i].rchild = 0;
	}
	for(int i = 1;i<=n0;i++) cin>>ht[i].weight;
	for(int i = n0+1;i<=n;i++){
		select(ht,i-1,s1,s2);
		ht[s1].parent=i; ht[s2].parent=i; 
		ht[i].lchild = s1;ht[i].rchild = i;	
		ht[i].weight = ht[s1].weight+ht[s2].weight;
	} 
	
}

//很好理解,但是不知道是否有漏洞

void CreateHaffmanCode(HaffmanTree ht,HaffmanCode hc,int n0){
	hc = new char*[n0+1];//从序号1开始
	cd = new char[n0];//从下标0开始,共n0个空间
	cd[n0-1] = '\0';
	
	for(int i = 1;i<=n0;i++){
		start = n0-1; //至多占用n0-1个空间,所以共n0个空间
		for(int c = i,f = ht[c].parent;f!=0;c = f,f = ht[f].parent)
			if(ht[c].lchild == c) cd[--start] = '0';
			else cd[--start] = '1';
		hc[i] = new char[n0-start];//n0个空间,减去未占用的
		strcpy(hc[i],&cd[start]);
			
	}
	
	delete cd;	
	
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值