文章目录

  • 构建
  • 原理图示
  • 代码实现
  • 节点
  • 构建函数
  • 筛选函数
  • 遍历
  • 结语


构建

采用父亲孩子表示法
先逐步分析再给出完整代码
注释很多,耐心看完全能懂

原理图示

(如果懂原理的话可以跳过)

哈夫曼树建立java 哈夫曼树的创建和遍历_霍夫曼树


哈夫曼树建立java 哈夫曼树的创建和遍历_哈夫曼树建立java_02


哈夫曼树建立java 哈夫曼树的创建和遍历_数据结构_03


哈夫曼树建立java 哈夫曼树的创建和遍历_数据结构_04

代码实现

节点
typedef struct
{    
    int weight;
    int parent,lchild,rchild;
}HTNode,*HuffmanTree;
构建函数
//HT是存放所有节点的数组,n是一开始权值的个数
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
	//m表示哈夫曼树总节点个数,s1,s2分别表示当前最小、第二小的节点
    int m,s1,s2,i;
    //只有一个节点,这就不需要构建了吧
    if(n<=1) return;
    
    //开局n个权值,然后两两组合的过程中会产生n-1新的数字,所以开辟2n-1的数组存放
    //或者理解为:n0 = n2+1,  N = n0+n2 = 2*n0-1  (n0代表度为0的节点,n2代表度为2的节点)    
    m = 2*n-1;
    //下标从1开始,所以这里m+1
    HT = new HTNode[m+1];
	//采用父亲孩子表示法
	//HT[i].parent存父节点的下标
	//HT[i].lchild, HT[i].rchild分别存左右孩子节点的下标
	//注意我们是从1开始的,现在全部初始化为0 
	for(i=1;i<=m;++i)              
    { 
		HT[i].parent=0;
		HT[i].lchild=0;  
		HT[i].rchild=0; 
	}
	//给n个权值赋值 
    for(i=1;i<=n;++i)
	{ 
	    cin >> HT[i].weight;
	}
	
	for(i=n+1;i<=m;++i) 
    {      
    	//Select函数是选出 当前 最小和第二小的节点,
    	//什么叫当前?怎么判断?具体后面解释
        Select(HT, i, s1, s2);
        //HT[s1],HT[s2]合成的新节点下标为i,将i存入parent
        HT[s1].parent= i;     
		HT[s2].parent= i;
		//相应的,HT[i]的左右孩子节点就是HT[s1],HT[s2]
        HT[i].lchild= s1;  
        HT[i].rchild= s2;
        //父亲的权值就是孩子的权值相加
        //每个被新合成的父亲都被依次(i)放到数组中                         
        HT[i].weight= HT[s1].weight + HT[s2].weight; 
    }                                            
}
筛选函数
void Select(HuffmanTree HT,int len,int &s1,int &s2)
{
//每次都给min1,min2赋较大的值,以便每次都能重新筛选符合条件的最小值
    int i,min1=32767,min2=32767;
    for(i=1;i<=len;i++)
    {
    //刚刚提到过如何判断当前
    //这时候我们parent初始赋值0就起到了判断作用
    //如果一个节点的parent不为0,就说明它已经参与过合并(权值相加合成父亲节点)
    //因为是二合一,实际上应该剔除两个(孩子),然后放入新的一个(父亲),但是我们没有剔除,而是根据parent的值是否为0来辨别        
    
		//找最小
		if(HT[i].weight<min1&&HT[i].parent==0)
        {
        
            s2=s1;
            //第二小的条件也要不断缩小
            min2=min1;
            min1=HT[i].weight;
            s1=i;
        }
        //找第二小
        else if(HT[i].weight<min2&&HT[i].parent==0)
        {    
        	min2=HT[i].weight;
            s2=i;
        }
    }
}

遍历

(老实说…数组的遍历还能玩出什么花来吗…)**

//依次打印权值、父节点下标、左右孩子节点下标(从1开始的从1开始的从1开始的!!!)
void print(HuffmanTree HT,int n)
{
    for(int i=1;i<=2*n-1;i++)
        cout << HT[i].weight << " " << HT[i].parent << " " << HT[i].lchild  << " " << HT[i].rchild << endl;
}

唔…干脆,主函数也一起给了?

int main()
{
    HuffmanTree HT;
    int n;
    cin >> n;
    CreatHuffmanTree(HT,n);
    print(HT,n);
    return 0;
}

结语

咳咳咳…画图繁琐,码字不易,看官阅读完之后要是觉得还行——不妨就点个赞吧!😝