哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。
哈夫曼樹的構造方法是貪心的每次選最小的幾個節點構造。
當k
>
2k>2
k>
2的時候需要預處理一下,因為可能最後一步合併操作的點數不到k個節點,這樣的話就不是最優的了。
k
>
2k>2
k>
2預處理方法:
當r em
ain=
(n−1
)mod
(k−1
)≠
0remain=(n-1)~mod~(k-1)\neq 0
remain
=(n−
1)mo
d(k−
1)
=0時:加入k−1
−rem
ai
nk-1-remain
k−1−re
main
個權重為0的虛擬節點。
將r am
ain+
1ramain+1
ramain
+1個節點先合併為1個節點。(有可能只有rem
ai
nremain
remain
個節點)
構造哈夫曼樹:
每次取最小的k
kk個數合併為乙個節點。
這裡很容易想到用優先佇列去寫,複雜度o(n
logn
)o(nlogn)
o(nlog
n)。如果陣列是有序的,我們可以用兩個佇列去優化一下,將原先的節點放入q1q1
q1,合併之後的節點放入q2q2
q2,這樣仍然滿足單調性,只需要每次取數的時候取兩個佇列中小的那個即可,複雜度o(n
)o(n)
o(n)
#include
#define fi first
#define se second
#define mp make_pair
using
namespace std;
typedef
long
long ll;
typedef pair<
int,
int>p;
const
double eps =
1e-8
;const
int ninf =
0xc0c0c0c0
;const
int inf =
0x3f3f3f3f
;const ll mod =
1e9+7;
const ll n =
1e5+5;
ll n,m,a[n]
;bool
check
(int k)
else
if(q2.
empty()
)else
else}}
sum+
=tmp;
if(q1.
empty()
&& q2.
empty()
)break
; q2.
push
(tmp);}
return sum<=m;
}int
main()
cout<'\n'
;return0;
}
#include
#define fi first
#define se second
#define mp make_pair
using
namespace std;
typedef
long
long ll;
typedef pair<
int,
int> pii;
const
double eps =
1e-8
;const
int ninf =
0xc0c0c0c0
;const
int inf =
0x3f3f3f3f
;const ll mod =
1e9+7;
const ll n =
1e6+5;
int n,m,a[n]
;inline
bool
check
(int k)
else
while
(true
)else
if(q2.
empty()
)else
else}}
sum+
=tmp;
if(q1.
empty()
&& q2.
empty()
)break
; q2.
push
(tmp);}
return sum<=m;
}int
main()
cout<'\n'
;return0;
}
荷馬史詩 k叉哈夫曼樹
題目描述 追逐影子的人,自己就是影子。荷馬 達達最近迷上了文學。但是由 奧德賽 和 伊利亞特 組成的鴻篇巨制 荷馬史詩 實在是太長了,達達想通過一種編碼方式使得它變得短一些。一部 荷馬史詩 中有 n 種不同的單詞,從 1 到 n 進行編號。其中第 i 種單詞出現的總次數為 wiwi。達達想要用 k ...
哈夫曼編碼 哈夫曼樹
1.定義 哈夫曼編碼主要用於資料壓縮。哈夫曼編碼是一種可變長編碼。該編碼將出現頻率高的字元,使用短編碼 將出現頻率低的字元,使用長編碼。變長編碼的主要問題是,必須實現非字首編碼,即在乙個字符集中,任何乙個字元的編碼都不是另乙個字元編碼的字首。如 0 10就是非字首編碼,而0 01不是非字首編碼。2....
哈夫曼樹 哈夫曼編碼
定義從a結點到b結點所經過的分支序列為從a結點到b結點的路徑 定義從a結點到b結點所進過的分支個數為從a結點到b結點的路徑長度 從二叉樹的根結點到二叉樹中所有結點的路徑長度紙盒為該二叉樹的路徑長度 huffman樹 帶權值路徑長度最小的擴充二叉樹應是權值大的外界點舉例根結點最近的擴充二叉樹,該樹即為...