贪心算法-哈夫曼树-(树的建立,带权路径长度,哈夫曼编码)

哈夫曼树中的名词意思:(ps:本想画个图的不知这上面怎么弄,就没弄了)

树的权值:每个树节点所在的那个数字。

路径:两个节点之间所经过的分支。

路径长度: 某一路径上的分支条数。

节点带权路径长度: 节点的权值*该节点的路径长度。

树带权路径长度:所有叶子节点的带全路径长度之和。

树带权路径长度:所有叶子节点的带全路径长度之和。

建立哈夫曼树:单独将数组中的每个值作为一个节点,依次选出剩余节点的最小与次小,并将其合为树结构的一部分。代码为:

 
btreenode *CreateHuffman(int a[],int n)
{
    int i;
    btreenode *s[n+1], *ss;
    for(int i = 0;idata = a[i];   //将树拆成森林,每棵树都只有一个根节点
        s[i]->left = s[i]->right = NULL;
    }
    for(int i  = 1;idatadata){        //比最小树小
                    t = k;
                    k = i;
                }
                else if(s[i]->datadata){  //比次小树小
                    t = i;
                }
                else{
                    ;
                }
            }
        }
           //由最小权值树和次最小权值树建立一棵新树,ss指向树根结点(以后依次建立)
           ss  = new btreenode;     //ss = (btreenode *)malloc(sizeof(btreenode))
           ss->data =   s[k]->data+s[t]->data;
           ss->left =   s[k];
           ss->right =  s[t];
           s[k] =  ss;  //关键点:将ss赋给s[k](k为上述找到的最小树下标,但这是s[k]代表的值已改变,同时把s[t]失效的置空,
                       //在这里起向下一个判断的作用if(s[j]){t = j;break;}
           s[t] = NULL;
    }
        free(s);   //释放分配空间
        return ss;
}

哈夫曼树的带权路径长度: 递归至树的叶子节点则此节点的路径长度为:(len值*所带的权值),否则每向下一层len+1(len为树层数):代码为:

//求哈夫曼树的带权路径长度  	
int WeightPathLength(btreenode* FBT, int len){          //参数len为树的层数 
	if(!FBT){  
	        return 0;  
	}  
	else{  
	    if(FBT->left ==NULL&&FBT->right ==NULL)//访问到叶子结点  
	        return FBT->data*len;  
	    else{               //访问到非叶子结点,进行递归调用,返回左右子树的带权路径长度之和,len递增  
	        return  WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1);//一定要记得加1  
	    }  
	}     
}  

哈夫曼编码:将编码值存到数组中,递归到叶子节点则输出数组保存的编码值,代码为:

//哈夫曼编码  
void HuffManCoding(btreenode* FBT, int len){   //参数len为树的层数 
	static int a[20];   					 //定义静态数组a,保存每个叶子的编码,数组长度至少是树深度减1 
	if(FBT){ 								//访问到叶子结点时输出其保存在数组a中的0和1序列编码  
	    if(FBT->left == NULL&&FBT->right == NULL){  
	        printf("结点权值为%d的编码:",FBT->data);  
	         for(int i = 0;ileft,len+1);  
	           a[len] = 1;  
	           HuffManCoding(FBT->right,len+1);  
	        }  
	}  
}  
完整代码为:
#include 
using namespace std;
typedef struct BTreeNode
{
    int  data;
    struct BTreeNode* left;
    struct BTreeNode* right;
}btreenode;
//建立哈夫曼树
btreenode *CreateHuffman(int a[],int n)
{
	int i;
	btreenode *s[n+1], *ss;
	for(int i = 0;idata = a[i];   //将树拆成森林,每棵树都只有一个根节点
	    s[i]->left = s[i]->right = NULL;
	}
	for(int i  = 1;idatadata){        //比最小树小
	                t = k;
	                k = i;
	            }
	            else if(s[i]->datadata){  //比次小树小
	                t = i;
	            }
	            else{
	                ;
	            }
	        }
	    }
	       //由最小权值树和次最小权值树建立一棵新树,ss指向树根结点(以后依次建立)
	       ss  = new btreenode;     //ss = (btreenode *)malloc(sizeof(btreenode))
	       ss->data =   s[k]->data+s[t]->data;
	       ss->left =   s[k];
	       ss->right =  s[t];
	       s[k] =  ss;  //关键点:将ss赋给s[k](k为上述找到的最小树下标,但这是s[k]代表的值已改变,同时把s[t]失效的置空,
	                   //在这里起向下一个判断的作用if(s[j]){t = j;break;}
	       s[t] = NULL;
	}
	    free(s);   //释放分配空间
		return ss;
}
//求哈夫曼树的带权路径长度
int WeightPathLength(btreenode* FBT, int len){          //参数len为树的层数
	if(!FBT){
        return 0;
	}
	else{
	    if(FBT->left ==NULL&&FBT->right ==NULL)//访问到叶子结点
	        return FBT->data*len;
	    else{               //访问到非叶子结点,进行递归调用,返回左右子树的带权路径长度之和,len递增
	        return  WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1);//一定要记得加1
	    }
	}
}
//哈夫曼编码
void HuffManCoding(btreenode* FBT, int len){   //参数len为树的层数
	static int a[20];   					 //定义静态数组a,保存每个叶子的编码,数组长度至少是树深度减1
	if(FBT){ 								//访问到叶子结点时输出其保存在数组a中的0和1序列编码
	    if(FBT->left == NULL&&FBT->right == NULL){
	         printf("结点权值为%d的编码:",FBT->data);
	         for(int i = 0;ileft,len+1);
	           a[len] = 1;
	           HuffManCoding(FBT->right,len+1);
	        }
	}
}
int main(){
	btreenode *s;
	int n;
	printf("从键盘输入待构造的哈夫曼树中带权叶子结点数n:");
	while(true){
	    scanf("%d",&n);
	    if(n>0){
	        break;
	    }
	    else{
	        printf("-------输入不合法,请重新输入!!\n");
	    }
	}
	int *a = (int *)malloc(n *sizeof(int));
	printf("从键盘输入%d个整数作为权值:",n);
	for (int i = 0; i < n; i++)
	    scanf("%d", &a[i]);
	s = CreateHuffman(a,n);
	printf("哈夫曼树的带权路径长度:");
	printf("%d\n", WeightPathLength(s, 0));
	printf("树中每个叶子结点的哈夫曼编码:\n");
	HuffManCoding(s,0);
	return 0;
}
贪心算法-哈夫曼树-(树的建立,带权路径长度,哈夫曼编码)_第1张图片


你可能感兴趣的:(数据结构与算法,哈夫曼树的基本操作)