0023算法笔记贪心算法哈夫曼编码问题.docx

上传人:b****6 文档编号:7567362 上传时间:2023-01-25 格式:DOCX 页数:18 大小:203.57KB
下载 相关 举报
0023算法笔记贪心算法哈夫曼编码问题.docx_第1页
第1页 / 共18页
0023算法笔记贪心算法哈夫曼编码问题.docx_第2页
第2页 / 共18页
0023算法笔记贪心算法哈夫曼编码问题.docx_第3页
第3页 / 共18页
0023算法笔记贪心算法哈夫曼编码问题.docx_第4页
第4页 / 共18页
0023算法笔记贪心算法哈夫曼编码问题.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

0023算法笔记贪心算法哈夫曼编码问题.docx

《0023算法笔记贪心算法哈夫曼编码问题.docx》由会员分享,可在线阅读,更多相关《0023算法笔记贪心算法哈夫曼编码问题.docx(18页珍藏版)》请在冰豆网上搜索。

0023算法笔记贪心算法哈夫曼编码问题.docx

0023算法笔记贪心算法哈夫曼编码问题

0023算法笔记——【贪心算法】哈夫曼编码问题

   1、问题描述

    哈夫曼编码是广泛地用于数据文件压缩的十分有效的编码方法。

其压缩率通常在20%~90%之间。

哈夫曼编码算法用字符在文件中出现的频率表来建立一个用0,1串表示各字符的最优表示方式。

一个包含100,000个字符的文件,各字符出现频率不同,如下表所示。

  有多种方式表示文件中的信息,若用0,1码表示字符的方法,即每个字符用唯一的一个0,1串表示。

若采用定长编码表示,则需要3位表示一个字符,整个文件编码需要300,000位;若采用变长编码表示,给频率高的字符较短的编码;频率低的字符较长的编码,达到整体编码减少的目的,则整个文件编码需要(45×1+13×3+12×3+16×3+9×4+5×4)×1000=224,000位,由此可见,变长码比定长码方案好,总码长减小约25%。

   前缀码:

对每一个字符规定一个0,1串作为其代码,并要求任一字符的代码都不是其他字符代码的前缀。

这种编码称为前缀码。

编码的前缀性质可以使译码方法非常简单;例如001011101可以唯一的分解为0,0,101,1101,因而其译码为aabe。

   译码过程需要方便的取出编码的前缀,因此需要表示前缀码的合适的数据结构。

为此,可以用二叉树作为前缀码的数据结构:

树叶表示给定字符;从树根到树叶的路径当作该字符的前缀码;代码中每一位的0或1分别作为指示某节点到左儿子或右儿子的“路标”。

   从上图可以看出,表示最优前缀码的二叉树总是一棵完全二叉树,即树中任意节点都有2个儿子。

图a表示定长编码方案不是最优的,其编码的二叉树不是一棵完全二叉树。

在一般情况下,若C是编码字符集,表示其最优前缀码的二叉树中恰有|C|个叶子。

每个叶子对应于字符集中的一个字符,该二叉树有|C|-1个内部节点。

   给定编码字符集C及频率分布f,即C中任一字符c以频率f(c)在数据文件中出现。

C的一个前缀码编码方案对应于一棵二叉树T。

字符c在树T中的深度记为dT(c)。

dT(c)也是字符c的前缀码长。

则平均码长定义为:

使平均码长达到最小的前缀码编码方案称为C的最优前缀码。

   

    2、构造哈弗曼编码

   哈夫曼提出构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼编码。

其构造步骤如下:

   

(1)哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。

   

(2)算法以|C|个叶结点开始,执行|C|-1次的“合并”运算后产生最终所要求的树T。

   (3)假设编码字符集中每一字符c的频率是f(c)。

以f为键值的优先队列Q用在贪心选择时有效地确定算法当前要合并的2棵具有最小频率的树。

一旦2棵具有最小频率的树合并后,产生一棵新的树,其频率为合并的2棵树的频率之和,并将新树插入优先队列Q。

经过n-1次的合并后,优先队列中只剩下一棵树,即所要求的树T。

   构造过程如图所示:

   具体代码实现如下:

   

(1)4d4.cpp,程序主文件

[cpp] viewplain copy

1.//4d4 贪心算法 哈夫曼算法  

2.#include "stdafx.h"  

3.#include "BinaryTree.h"  

4.#include "MinHeap.h"  

5.#include    

6.using namespace std;   

7.  

8.const int N = 6;  

9.  

10.template class Huffman;  

11.  

12.template   

13.BinaryTree HuffmanTree(Type f[],int n);  

14.  

15.template   

16.class Huffman  

17.{  

18.    friend BinaryTree HuffmanTree(Type[],int);  

19.    public:

  

20.        operator Type() const   

21.        {  

22.            return weight;  

23.        }  

24.    //private:

  

25.        BinaryTree tree;  

26.        Type weight;  

27.};  

28.  

29.int main()  

30.{  

31.    char c[] = {'0','a','b','c','d','e','f'};  

32.    int f[] = {0,45,13,12,16,9,5};//下标从1开始  

33.    BinaryTree t = HuffmanTree(f,N);  

34.  

35.    cout<<"各字符出现的对应频率分别为:

"<

36.    for(int i=1; i<=N; i++)  

37.    {  

38.        cout<

"<

39.    }  

40.    cout<

41.  

42.    cout<<"生成二叉树的前序遍历结果为:

"<

43.    t.Pre_Order();  

44.    cout<

45.  

46.    cout<<"生成二叉树的中序遍历结果为:

"<

47.    t.In_Order();  

48.    cout<

49.  

50.    t.DestroyTree();  

51.    return 0;  

52.}  

53.  

54.template  

55.BinaryTree HuffmanTree(Type f[],int n)  

56.{  

57.    //生成单节点树  

58.    Huffman *w = new Huffman[n+1];  

59.    BinaryTree z,zero;  

60.  

61.    for(int i=1; i<=n; i++)  

62.    {  

63.        z.MakeTree(i,zero,zero);  

64.        w[i].weight = f[i];  

65.        w[i].tree = z;  

66.    }  

67.  

68.    //建优先队列  

69.    MinHeap> Q(n);  

70.    for(int i=1; i<=n; i++) Q.Insert(w[i]);  

71.  

72.    //反复合并最小频率树  

73.    Huffman x,y;  

74.    for(int i=1; i

75.    {  

76.        x = Q.RemoveMin();  

77.        y = Q.RemoveMin();  

78.        z.MakeTree(0,x.tree,y.tree);  

79.        x.weight += y.weight;  

80.        x.tree = z;  

81.        Q.Insert(x);  

82.    }  

83.  

84.    x = Q.RemoveMin();  

85.  

86.    delete[] w;  

87.  

88.    return x.tree;  

89.}  

   

(2)BinaryTree.h二叉树实现

[cpp] viewplain copy

1.#include  

2.using namespace std;  

3.  

4.template  

5.struct BTNode  

6.{  

7.    T data;  

8.    BTNode *lChild,*rChild;  

9.  

10.    BTNode()  

11.    {  

12.        lChild=rChild=NULL;  

13.    }  

14.  

15.    BTNode(const T &val,BTNode *Childl=NULL,BTNode *Childr=NULL)  

16.    {  

17.        data=val;  

18.        lChild=Childl;  

19.        rChild=Childr;  

20.    }  

21.  

22.    BTNode* CopyTree()  

23.    {  

24.        BTNode *nl,*nr,*nn;  

25.  

26.        if(&data==NULL)  

27.        return NULL;  

28.  

29.        nl=lChild->CopyTree();  

30.        nr=rChild->CopyTree();  

31.  

32.        nn=new BTNode(data,nl,nr);  

33.        return nn;  

34.    }  

35.};  

36.  

37.  

38.template  

39.class BinaryTree  

40.{  

41.    public:

  

42.        BTNode *root;  

43.        BinaryTree();  

44.        ~BinaryTree();  

45.  

46.        void Pre_Order();  

47.        void In_Order();  

48.        void Post_Order();  

49.  

50.        int TreeHeight()const;  

51.        int TreeNodeCount()const;  

52.  

53.        void DestroyTree();  

54.        void MakeTree(T pData,BinaryTree leftTree,BinaryTree rightTree);  

55.        void Change(BTNode *r);  

56.  

57.    private:

  

58.        void Destroy(BTNode *&r);  

59.        void PreOrder(BTNode *r);  

60.        void InOrder(BTNode *r);  

61.        void PostOrder(BTNode *r);  

62.  

63.        int Height(const BTNode *r)const;  

64.        int NodeCount(const BTNode *r)const;  

65.};  

66.  

67.template  

68.BinaryTree:

:

BinaryTree()  

69.{  

70.    root=NULL;  

71.}  

72.  

73.template  

74.BinaryTree:

:

~BinaryTree()  

75.{  

76.      

77.}  

78.  

79.template  

80.void BinaryTree:

:

Pre_Order()  

81.{  

82.    PreOrder(root);  

83.}  

84.  

85.template  

86.void BinaryTree:

:

In_Order()  

87.{  

88.    InOrder(root);  

89.}  

90.  

91.template  

92.void BinaryTree:

:

Post_Order()  

93.{  

94.    PostOrder(root);  

95.}  

96.  

97.template  

98.int BinaryTree:

:

TreeHeight()const  

99.{  

100.    return Height(root);  

101.}  

102.  

103.template  

104.int BinaryTree:

:

TreeNodeCount()const  

105.{  

106.    return NodeCount(root);  

107.}  

108.  

109.template  

110.void BinaryTree:

:

DestroyTree()  

111.{  

112.    Destroy(root);  

113.}  

114.  

115.template  

116.void BinaryTree:

:

PreOrder(BTNode *r)  

117.{  

118.    if(r!

=NULL)  

119.    {  

120.        cout<data<<' ';  

121.        PreOrder(r->lChild);  

122.        PreOrder(r->rChild);  

123.    }  

124.}  

125.  

126.template  

127.void BinaryTree:

:

InOrder(BTNode *r)  

128.{  

129.    if(r!

=NULL)  

130.    {  

131.        InOrder(r->lChild);  

132.        cout<data<<' ';  

133.        InOrder(r->rChild);  

134.    }  

135.}  

136.  

137.template  

138.void BinaryTree:

:

PostOrder(BTNode *r)  

139.{  

140.    if(r!

=NULL)  

141.    {  

142.        PostOrder(r->lChild);  

143.        PostOrder(r->rChild);  

144.        cout<data<<' ';  

145.    }  

146.}  

147.  

148.template  

149.int BinaryTree:

:

NodeCount(const BTNode *r)const  

150.{  

151.    if(r==NULL)  

152.        return 0;  

153.    else  

154.        return 1+NodeCount(r->lChild)+NodeCount(r->rChild);  

155.}  

156.  

157.template  

158.int BinaryTree:

:

Height(const BTNode *r)const  

159.{  

160.    if(r==NULL)  

161.        return 0;  

162.    else  

163.    {  

164.        int lh,rh;  

165.        lh=Height(r->lChild);  

166.        rh=Height(r->rChild);  

167.        return 1+(lh>rh?

lh:

rh);  

168.    }  

169.}  

170.  

171.template  

172.void BinaryTree:

:

Destroy(BTNode *&r)  

173.{  

174.    if(r!

=NULL)  

175.    {  

176.        Destroy(r->lChild);  

177.        Destroy(r->rChild);  

178.        delete r;  

179.        r=NULL;  

180.    }  

181.}  

182.  

183.template  

184.void BinaryTree:

:

Change(BTNode *r)//将二叉树bt所有结点的左右子树交换  

185.{  

186.    BTNode *p;  

187.    if(r){   

188.        p=r->lChild;  

189.        r->lChild=r->rChild;  

190.        r->rChild=p; //左右子女交换  

191.        Change(r->lChild);  //交换左子树上所有结点的左右子树  

192.        Change(r->rChild);  //交换右子树上所有结点的左右子树  

193.    }  

194.}  

195.  

196.template  

197.void BinaryTree:

:

MakeTree(T pData,BinaryTree leftTree,BinaryTree rightTree)  

198.{  

199.    root = new BTNode();  

200.    root->data = pData;  

201.    root->lChild = leftTree.root;  

202.    root->rChild = rightTree.root;  

203.}  

   (3)MinHeap.h最小堆实现

[cpp] viewplain copy

1.#include   

2.using namespace std;  

3.template  

4.class MinHeap  

5.{  

6.    private:

  

7.        T *heap; //元素数组,0号位置也储存元素  

8.        int CurrentSize; //目前元素个数  

9.        int MaxSize; //可容纳的最多元素个数  

10.  

11.        void FilterDown(const int start,const int end); //自上往下调整,使关键字小的节点在上  

12.        void FilterUp(int start); //自下往上调整  

13.  

14.    public:

  

15.        MinHeap(int n=1000);  

16.        ~MinHeap();  

17.        bool Insert(const T &x); //插入元素  

18.  

19.        T RemoveMin(); //删除最小元素  

20.        T GetMin(); //取最小元素  

21.  

22.        bool IsEmpty() const;  

23.        bool IsFull() const;  

24.        void Clear();  

25.};  

26.  

27.template  

28.MinHeap:

:

MinHeap(int n)  

29.{  

30.    MaxSize=n;  

31.    heap=new T[MaxSize];  

32.    CurrentSize=0;  

33.}  

34.  

35.template  

36.MinHeap:

:

~MinHeap()  

37.{  

38.    delete []heap;  

39.}  

40.  

41.template  

42.void MinHeap:

:

FilterUp(int start) //自下往上调整  

43.{  

44.    int j=start,i=(j-1)/2; //i指向j的双亲节点  

45.    T temp=heap[j];  

46.  

47.    while(j>0)  

48.    {  

49.        if(heap[i]<=temp)  

50.            break;  

51.        else  

52.        {  

53.   

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 面试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1