; G. `* L/ b7 _ score=’及格’; , m4 K8 j9 }6 r R, c 4 k' S, q. A, T9 S9 Y; Z, |; Relse if ( x<80)) X. ~9 W+ M: G$ X
+ C2 _5 M# {0 _
score=’中’;( v9 \9 Z$ v8 u. t' Y
' b- z/ A5 Q) e" C' I5 ielse if ( x<90)6 G" B( X& O0 {; o/ r( J
# V- K, T+ Z; f( j* S1 ^6 a score=’良’;# u6 x9 Z7 X2 A* q, M( C
+ n I% ?5 F! [; f9 ]else7 a j$ ?9 S& X* g6 x7 z, Q
3 h+ J7 g1 L9 [/ q" B
score=’优’;8 `3 `8 A! G( ]7 y" [ L$ x2 E2 B
1 S! U& ~! D) k$ V' e* m
此判定过程可以用图6.33(a)的判定树来表示。如果学生规模很大,该算法需反复多次执行,就应该考虑算法执行的时间问题。在实际应用中,学生的成绩呈正态分布,大部分在70~89分之间,优秀和不及格的概率较小。假设不及格、及格、中、良、优的百分比为5%、12%、40%、35%、8%,则上述算法80%以上的成绩需要进行三次或三次以上的比较才能得到结果。若以这些百分比值5,12,40,35,8为权值,使用哈夫曼算法来构造一棵判定树,则得到图6.33(b)所示的判定过程,可使多数成绩经过较少的比较即可得到结果。但由于每个判定框都有两次比较,将两次比较分开,得到如图6.33(c)所示的判定树,按此判定树构造程序,显然可以大大减少比较次数。 % g2 \7 _5 C+ t7 o u' Q ( P2 p$ c) g7 P" i0 j, S% W7 p x x % V3 r9 u/ Q" J9 h
; [* n/ u" d- Q0 q. j( j5 I' h9 q
" d% G# h, i9 P+ Y% F
0 F% L# j0 W/ h& s2 p5 K& G% H- T8 \5 I5 \" m; E) q( d
) e: B+ O) L' z8 a7 g
x<60 70≤x<806 u) k( m0 i* t. i
0 u6 S# ]6 N R$ S6 ~
Y N Y N # z R1 A% }7 o2 x% d6 n+ _. l# h ) S9 b% p; p b7 i( N7 }: f 不及格 x<70 中 80≤x<90 ; ~3 i9 m1 M# B( C, T7 C A+ h5 M* |: {4 {9 \, Z Y N Y N F& c# J9 U6 o6 S" ?: c! G- {, y l
及格 x<80 良 60≤x<702 N: _1 H1 k \" X/ p% ^
% ^5 o5 k+ U" l- ~5 {5 S Y N Y N " {1 ]. d" `% `- O$ P( j8 Z E, N1 l: Z: @- C5 ]; R; {
中 x<90 x<60 及格" q1 a6 R5 x$ U \7 R' s/ A5 v
' C+ d7 \" ^) B) B% i Y N Y N . H, m8 N9 [, A6 e# J [9 `/ I! J& r: |- z& v
良 优 不及格 优 , A# c4 `* i3 H5 X+ z: f$ q. W( ?: }- k" p
(a) (b) # W/ Y; D4 q( h" a( N$ [$ f$ f6 D& T/ p3 E3 I5 t6 G; e
x( q6 k2 q& A+ ?$ V+ J( J! x* y5 p7 H
+ {3 X1 m% S' o" g 4 D' _! P6 `1 {+ y9 D! R! z* s
5 A0 x! j5 t5 y# ~ x<80 , A+ h* C; m! f8 ?/ t . ]7 ^) B5 h/ E* }; a, b. a Y( Z3 Z* d, C) E. K3 v9 ]( c
* ~5 {, F( _& M
x<70 x<90 % l. I9 t$ \# d# B& X, n( E4 I" r" \0 m( D
Y N Y N ( m ~5 B+ r9 Q5 h! g( o ! {2 U0 t6 U2 `0 g6 W w x<60 中 良 优 4 F" H# `1 W2 O# N/ q+ A ! o4 z5 I# H( c, Q Y N1 Z2 v: c8 m7 A2 Z. e4 f
& i6 r! q9 _# R6 X4 d 不及格 及格 & p# M; A: l5 ], H0 Y. M8 u, A: Q2 h/ }* `9 i9 G
(c)9 L) u+ z' O* r+ D ~$ C0 i/ `
+ |5 Z1 A- _" v6 b7 @
图6.33 百分制转换五级制的判定过程0 O- o2 ` e$ y6 t# g% t" t# V
" o! e' E+ u7 H; b. v' j7 H: m
+ ]& e$ Y& h) X d, x * L! r8 q1 k; s" G2 o7 f! S哈夫曼树在通信、编码和数据压缩等技术领域也有着广泛的应用。下面我们介绍哈夫曼树在数据编码中的应用,即数据的最小冗余编码问题。 ; [6 R# w/ J$ x1 C" R7 {* \ & |) t# D& m6 S" {% t1 g在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。显然编码的长度取决报文中不同字符的个数。若报文中可能出现26个不同字符,则固定编码长度为5。然而,传送报文时总是希望总长度尽可能短。在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码。但这样长短不等的编码又会产生一个新问题,即如何解译成原文?除非设计时能够保证任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀,符合此要求的编码称为前缀编码。! l9 ^$ k: X: V3 Y
6 i8 ^' ?6 r( S: ^; N
为使不等长编码为前缀编码,可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,求出此树的最小带权路径长度就等于求出了传送报文的最短长度。因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短。, Y" l' M+ _, f$ [
+ p! N: u* B" v
我们用上述各字母出现的次数{8,4,5,3,1,1}作为权构造哈夫曼树,如图6.36所示。约定左分支表示字符“0”,右分支表示字符“1”,则可以从根结点到叶子结点的路径的分支上的字符组成的字符串作为该叶子对应字符的编码。可以证明,如此得到的必为二进制前缀编码,而且是一种最优前缀编码。我们称这样的树为哈夫曼编码树,由此得到的编码称为哈夫曼编码。本例中字母A、E、R、T、F、D的哈夫曼编码分别为11、00、01、011、0100、0101。可以看出,出现次数较多的字母A、E、R,具有最短的编码,长度均为2;而出现次数最少的字母F、D,具有最长的编码,长度均为4。报文的最短传送长度为: 0 w: l3 T/ D3 {
' A% i& \. B" T6 A
64 J8 G2 [* n' y1 ~. Q
) h1 r5 H! S# U L=WPL=S(wklk)=4×2+5×2+8×2+3×3+1×4+1×4=51* g x) ^! X: Y& R$ P
; ?9 z9 z8 {. H8 P. \0 L
k=14 k/ @9 \5 b" Z5 j
2 _/ ^( B9 {9 U# O$ ]) `' x- |
若采用等长编码,报文的传送长度为 5 d) B1 {/ I2 {. L4 t( S% r2 ^. l7 b g! s ?
L=8×3+4×3+5×3+3×3+1×3+1×3=66 7 E) `* X3 {* e/ p( C6 l& F - G' f6 h- r& F显然,哈夫曼编码比等长编码所得到的报文长度要短得多。哈夫曼编码是最优前缀编码。 1 G" a' F g2 N4 r1 G# O$ R8 V2 O% ^1 @+ s R) Z* x* [
* R$ R! t7 i! ^
5 a- ?* {" }# I. d/ X# C8 y* p
22. j4 ~" E, G4 M# V! z) Q
% U$ O; S8 s. F6 X% y0 z
0 19 Y! ?4 G+ @1 D/ S1 e5 n$ I$ d% t
7 M! @5 }% J* c2 G0 E# S8 g; p; w9 13 " B& r8 h, |3 ^" B8 \- | 5 ~! V6 ?8 K, g) S& t( E 0 1 0 1 . n1 D: z- Y8 g o, z/ B" V% L4 P- x0 s# |3 P9 R( b% ]
4 5 5 8$ L; u6 C0 q, b, M$ K" q
6 z) y3 R& c3 L' {# `7 ?" Z6 }* E
E 0 1 R A 2 l0 M$ l5 v T& u( O: ?" {# F+ Z: b5 c. P5 q# T. u( R3 Y* N) ]
2 3( y2 Z5 A, W9 |+ b0 c8 `/ D: G1 m
# y9 r. Q' w e' m: U9 ] 0 1 T! W8 q9 _: J" b
/ A' J% m3 K9 V& h1 l2 w7 h/ _ 1 1 1 |9 y* t1 ]- o# s' @. ` G4 i* y" [# ]4 Y) e/ E% W1 l' H" r
F D % d( r5 F% C, T8 B: _5 P7 j% E# I H& W/ {3 g; h5 y# w
图6. 36 哈夫曼编码树2 w1 ^7 N, O* } V( ]
4 h- y, z, o; _2 m) [: l+ h% Y一个任意长度的编码序列可被唯一地翻译为一个字符序列(单词)。依次取出编码序列中的0或1,从哈夫曼编码树的根结点开始寻找一条路径。若为0,则沿着左分支向下走;若为1,则沿着右分支向下走。每到达一个叶子外结点时,就译出一个相应的字符,然后再回到哈夫曼树的根结点处,依次译出余下的字符,最后得到一个单词。作者: liuyaliss 时间: 2009-9-6 15:10
哈夫曼树的应用* s/ T/ o2 q, H& Z; {8 ]* _6 r/ h
哈夫曼树的应用十分广泛,在不同的应用中,对叶子结点的权和带权路径长度有不同的解释。' Q1 o+ n+ {; P. R9 L, S% b
3 ]& |& t0 A0 Q8 B: w+ ]5 r3 u. z score=’不及格’; . Q& n; k* t+ I0 [7 e! T! ~ / U# U# g# l3 relse if ( x<70)3 ]' G- e: e& o& q# U) X
. ^3 I3 w \: f7 @ score=’及格’;7 d* b2 w9 v% {4 X/ n- u% E: W
, L! a+ d t9 d; Velse if ( x<80) ! a/ V) Z8 I# X, N$ Q( [! B* P$ {5 c, w6 t5 _' v
score=’中’; 5 a- j0 t2 f& p0 W9 [1 k9 D/ Q7 D6 m2 f4 C$ }8 {
else if ( x<90)% E; \, M3 m) z8 h6 d! t; B
! Y, ^+ B6 J9 ], b: M+ I0 O
score=’良’;6 l2 a2 @" n& L5 r$ p
) O1 t0 W9 v |( ~2 w2 Velse, b d7 b0 S9 O& j4 Q/ g6 n5 ?
: H: \2 o5 C: d# s
score=’优’;9 {3 D& S$ ]8 {4 J, \- y0 ]4 \3 A' B
' I" @* V7 k" @6 ^8 M. ^1 z此判定过程可以用图6.33(a)的判定树来表示。如果学生规模很大,该算法需反复多次执行,就应该考虑算法执行的时间问题。在实际应用中,学生的成绩呈正态分布,大部分在70~89分之间,优秀和不及格的概率较小。假设不及格、及格、中、良、优的百分比为5%、12%、40%、35%、8%,则上述算法80%以上的成绩需要进行三次或三次以上的比较才能得到结果。若以这些百分比值5,12,40,35,8为权值,使用哈夫曼算法来构造一棵判定树,则得到图6.33(b)所示的判定过程,可使多数成绩经过较少的比较即可得到结果。但由于每个判定框都有两次比较,将两次比较分开,得到如图6.33(c)所示的判定树,按此判定树构造程序,显然可以大大减少比较次数。: _. E& {; c- |; i. r0 P$ C6 D
Z9 h- L7 C" K! y9 z, V x x ( }2 |' q/ r" v. P
% ]4 _* R8 A! m6 ]& z$ C* a0 b1 u
6 u; C6 w& A6 G! ^, }" Z* A* l
" z- |+ a2 z/ n- h4 ]1 j# H1 m) ?) b1 I( o' d- e% z K* ^( M9 q7 m/ Q! \9 g
8 X1 O* }; E7 J- n# Y, ?0 n x<60 70≤x<806 p Y' C# @9 v/ v6 Y& a4 d8 s
2 x; e3 ^* A z# D
Y N Y N 5 x- ?* w' o c8 R7 Y1 [) w5 b K: C0 R. u4 I# _: g' V' G0 {+ N
不及格 x<70 中 80≤x<90 n; z% L7 w( M ' x" H/ _# {% i Y N Y N 4 \- ~1 c3 X, \5 x
5 N$ Z) ~* A' Q
及格 x<80 良 60≤x<70# P% M/ |- `# _& n+ H
/ R' \, p0 \# z' z
Y N Y N* {6 g2 T- S# b4 \( F o+ R( }
% `% u* R' O3 g5 J0 }& M3 V 中 x<90 x<60 及格 5 s* }7 M2 E7 f6 T. z2 z0 y9 r2 |& K/ t$ D
Y N Y N 6 C w4 ~2 ^8 o2 _) Z9 H0 x/ @
: X2 L y/ W1 w& O7 Y 良 优 不及格 优7 z8 u7 f& s1 r
- s6 K0 a6 u" j [1 Y+ M(a) (b) 6 L: a/ ?9 D9 v6 o/ U' W1 A% d8 T$ }" e$ v4 H! @
x * l' T" L# B$ R 4 J2 C3 x7 C, D1 Z' m! w% `" l 0 l& f r+ C8 J( H: O. e* @0 X
, o& }8 E) ]. E0 ?7 M- j; s( T
x<80' k7 {& Q% {0 |* e, I
. R6 T* A. V; E4 k
Y6 K& `: N. V9 [; G& @+ A4 x( c
. P- S) H+ I4 N' q$ n* q# }
x<70 x<90 8 r& l# Y# a% n* k/ y+ Z" O1 ], r2 {- ~, J' K
Y N Y N $ @; |# h8 ^' G0 y4 W u R% x: ]+ T1 N6 {7 W9 P x<60 中 良 优4 m( m3 H( r* m" F4 I6 {
5 s7 ]$ k& b+ {1 S& y9 \, b
Y N 0 p# t& }2 R& |) {, J # G/ ]( x7 g6 {" ~ 不及格 及格 8 e# c6 i% J5 ^ * J( e1 p# x3 R7 k (c), U7 v2 N! \, d/ |
9 ?- Y6 v6 _4 u2 A * d/ ~$ v3 ]9 [% m. v' @ 3 S5 `3 ^' S' l/ k* {1 q哈夫曼树在通信、编码和数据压缩等技术领域也有着广泛的应用。下面我们介绍哈夫曼树在数据编码中的应用,即数据的最小冗余编码问题。 / b: T% ]. C) G3 v+ L0 j6 w+ i7 L1 G! v# t8 J4 c* ]) g2 _
在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。显然编码的长度取决报文中不同字符的个数。若报文中可能出现26个不同字符,则固定编码长度为5。然而,传送报文时总是希望总长度尽可能短。在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码。但这样长短不等的编码又会产生一个新问题,即如何解译成原文?除非设计时能够保证任何一个字符的编码都不是同一字符集中另一个字符的编码的前缀,符合此要求的编码称为前缀编码。 $ k, u; y0 S1 L0 p9 W& f 6 i: n% [5 g- _6 V. m- @3 K为使不等长编码为前缀编码,可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,求出此树的最小带权路径长度就等于求出了传送报文的最短长度。因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短。 " ?( _; G7 k! D: a$ n * F* _ X9 L8 X0 F; Z( W! c, v8 `我们用上述各字母出现的次数{8,4,5,3,1,1}作为权构造哈夫曼树,如图6.36所示。约定左分支表示字符“0”,右分支表示字符“1”,则可以从根结点到叶子结点的路径的分支上的字符组成的字符串作为该叶子对应字符的编码。可以证明,如此得到的必为二进制前缀编码,而且是一种最优前缀编码。我们称这样的树为哈夫曼编码树,由此得到的编码称为哈夫曼编码。本例中字母A、E、R、T、F、D的哈夫曼编码分别为11、00、01、011、0100、0101。可以看出,出现次数较多的字母A、E、R,具有最短的编码,长度均为2;而出现次数最少的字母F、D,具有最长的编码,长度均为4。报文的最短传送长度为: + _% I2 g! V& @* b) J, C. s, I4 c; z9 Y5 h8 V% p5 s5 k
60 D( m9 Z4 `! Z! C& l
; V) m, A7 _/ _ w \
L=WPL=S(wklk)=4×2+5×2+8×2+3×3+1×4+1×4=51 ( U( [; h7 o! K3 C. e: U! S( e * X6 t& B' S c0 u1 [( E k=1* {9 B. v% O. K8 }& g' s* X
) d% m6 H! G. T; s: \若采用等长编码,报文的传送长度为 : T! c8 z8 B% \" E4 R9 |: t7 u
( T4 X- V4 H+ X4 c# K2 YL=8×3+4×3+5×3+3×3+1×3+1×3=66 |- M1 A$ |4 r7 i. W E0 K: [: {+ X% l+ a/ F: Z
显然,哈夫曼编码比等长编码所得到的报文长度要短得多。哈夫曼编码是最优前缀编码。, u& j* X* B; n; ]2 s
! m7 \2 g* N. F9 m6 I6 j6 P
8 ^8 L5 X3 m+ X% |. O6 V s2 X; e
22 . |3 i+ d+ ~# A" A: @1 k* E) H0 C) I1 V. D( _ {
0 1 ! x5 [0 `' B3 j. ^, ?1 J$ q / ?! `+ F5 l1 i- _2 C) x9 132 ~- k( e2 E l5 Q0 a( K
7 G) C7 Q( Y* T# G- a+ p( H 0 1 0 1 ) h+ z; R' B. a 4 q) G! s: z, ?" j. `8 i5 U0 b 4 5 5 80 L+ _( g5 O( ?! ?' Q( x
( \/ L+ Z9 w$ {" Z8 q E 0 1 R A1 ]+ ^, ^$ x4 t- ]/ l
" M- M3 I. E4 s n& P0 h F! k
2 3 1 M+ |& P; o6 R% b$ u. {! O4 u4 S9 h) W7 t/ s' h6 C7 y: s' [
0 1 T 2 I. P3 V! V- d. `8 [! X: T* X ! t$ O, }2 k6 C/ Q 1 1 ! i1 ^. O& i+ }" g. I9 r( G5 V8 ~
F D 6 N7 M$ m! h7 G/ n% S. h/ R9 V5 `: E( I% n) T3 _
图6. 36 哈夫曼编码树) k" a. y, p. O' O# E