Find the weighted path length of Huffman tree

The establishment process of Huffman tree:

First get the set of the entire leaf node:

 Find the weighted path length algorithm of the Huffman tree:

According to the book, the common algorithm for finding the weighted path length of the Huffman tree is: multiply the path length from the leaf node weight:

WPL=7*2+5*2+5*2+3*3+2*3=49

Another algorithm for finding WPL is: the sum of the weights of non-leaf points:

WPL=22+12+10+5=49

This method is not unreasonable. It should be that the path lengths of the two leaf nodes under the same node are the same, and the path length of the leaf nodes can be fully reflected in its parent nodes.

This algorithm is relatively simple, you can directly ignore the steps of building a tree, and directly calculate the WPL (of course, you must understand how to calculate the WPL)

The main idea of ​​the algorithm:

1. First sort the obtained set of elements; (descending order. Ascending order is also OK, please try it yourself)

2. Sum the two elements at the end of the array (the weights of the parent nodes of the two nodes), put the result in the penultimate position of the array and subtract 1 from the length of the array

3. Accumulate the summation results each time. (that is, the weight of non-leaf nodes)

Note: This algorithm is not applicable when the collection elements are too small, and special processing is required, otherwise the array will go out of bounds.

C language implementation:

#include<stdio.h>
#include<malloc.h>
// 算法思想:
// 本题主要为求哈夫曼树的带权路径长度,故未将重点放在建树上
// Huffman树的带权路径长其实就是其非叶子结点的权值和

//排序算法
void sort(int *data,int n){
    int i,j;
    for(i =0;i<n;++i){
        for (j = 0;  j< n-i; ++j) {
            if(data[j]<data[j+1]){
                int t = data[j+1];
                data[j+1] = data[j];
                data[j] = t;
            }
        }
    }
}

int main() {
    int n, *data,i,sum =0,x;
    scanf("%d", &n);
    //动态开辟数组
    data = (int *) malloc(sizeof(int)*n);
    for(i =0;i<n;++i)
        scanf("%d",&data[i]);
    if(n<=2){   //当集合过小时,不适用本算法,特殊处理
        for(i =0;i<n;++i)
            sum += data[i];
        printf("%d",data[0]+data[1]);
        return 0;
    }
    while(1){
        sort(data,n);   //先对数组排序(降序)
        x=data[n-1]+data[n-2];  //将末尾两元素求和(上层结点权值)
        data[n-2] = x;  //消除原来两元素,增加新元素
        sum+=x; //累计非叶子结点权值和
        --n;    //数组长度减1
        if(n==1)    //当数组中只剩下一个元素时,得出结果
            break;
    }
    printf("%d\n",sum);
}

Run the test:

 

Guess you like

Origin blog.csdn.net/weixin_64811333/article/details/128116060