哈夫曼樹求長度專題(WPL,總長度,編碼長度的均值)均不採用建樹法

思路

因爲哈夫曼樹的特殊性質,我們在求最小總長度、WPL、長度均值的時候,均不採用建樹法.
方向:哈夫曼樹的編碼長度等於各個葉節點權值與路徑長度乘積之和,同時這個值等於非葉節點之和。

非葉節點的權值之和=路徑葉節點權值=哈夫曼編碼的所有元素總長(編碼長度元素個數==路徑*權值)

題目一:求WPL

題目描述
哈夫曼樹,第一行輸入一個數n,表示葉結點的個數。需要用這些葉結點生成哈夫曼樹,根據哈夫曼樹的概念,這些結點有權值,即weight,題目需要輸出所有結點的值與權值的乘積之和。
輸入描述:
輸入有多組數據。
每組第一行輸入一個數n,接着輸入n個葉節點(葉節點權值不超過100,2<=n<=1000)。
輸出描述:
輸出權值。
示例1
輸入
5
1 2 2 5 9
輸出
37

代碼:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;
    scanf("%d",&n);
    vector<int>myvector;
    while(n--)
    {
        int x;
        scanf("%d",&x);
        myvector.push_back(x);
        
    }
    sort(myvector.begin(),myvector.end());
     int sum=0;
    while(myvector.size()>1)
    {
       
        int a=myvector[0];
        int b=myvector[1];
        sum=sum+a+b;
        myvector.erase(myvector.begin(),myvector.begin()+2);
        myvector.push_back(a+b);
        sort(myvector.begin(),myvector.end());
    }
    cout<<sum<<endl;
    return 0;
}

第二題:字符串的哈夫曼編碼長度

思路:這就是不把權值給你,你自行判斷權值,再進行求解,大同小異

題目:

字符串的哈夫曼編碼長度
問題描述:
給定一個字符串(長度不超過100),求哈夫曼編碼的最短長度

樣例輸入:
輸入1:
abbcccdddd
輸出1:
19
輸入2:
we will we will r u
輸出2:
50

代碼

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100;
 
string str;
map<char, int> mp;
priority_queue<int, vector<int>, greater<int> >q;
 
int main(){ 
    getline(cin, str);
    int len = str.length();
    for(int i = 0; i < len; i++){
       if(mp.find(str[i]) == mp.end()){
            mp[str[i]] = 1;
       }
       else{
            mp[str[i]]++;
       }
    }
    for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
        q.push(it->second);
    }
    int ans = 0;
    while(q.size() != 1){
        int a, b, temp;
        a = q.top();
        q.pop();
        b = q.top();
        q.pop();
        temp = a + b;
        ans += temp;
        q.push(temp);
    }
    cout << ans << endl;
    return 0;
    }

第三題:求哈夫曼編碼平均長度

注意:這裏可能是兩種處理方式:
第一種最簡單:wpl/所有權值和,這就不說了
第二種較困難:是每個權值編碼的長度和除以葉子的個數(見下面題目)

題目:

求霍夫曼編碼長度
輸入:
兩行
第一行:個數N
第二行:N個以空格隔開的數,表示這N個字符的出現次數
輸出:
一行,哈夫曼編碼的平均長度
樣例輸入:
6
1 3 6 2 7 3
樣例輸出:
2.666667

代碼:

#include <bits/stdc++.h>
using namespace std;

struct Point{  //利用truenum進行求結果,利用num進行排序。每次排序有順序要求的!
	int num;
	int truenum;
	Point(int n,int t):num(n),truenum(t){}
	bool operator<(const Point& c)const{
		if(num==c.num) return truenum>c.truenum;
		else return num>c.num;
	}
};
 
int main()
{
	int n;
	while(cin>>n)
	{
		priority_queue<Point>myqueue;
		for(int i=0;i<n;i++)
		{
			int x; cin>>x;
			myqueue.push(Point(x,1));
		}
		double sum=0;
		while(myqueue.size()!=1)
		{
			Point a=myqueue.top();
			myqueue.pop();
			Point b=myqueue.top();
			myqueue.pop();
			sum+=(a.truenum+b.truenum); 
			myqueue.push(Point(a.num+b.num,a.truenum+b.truenum));
		}
		printf("%.6lf\n",(double)sum/n);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章