数据结构之哈夫曼树

  数据结构之哈夫曼树  2011-08-14 15:26:48

分类: C/C++

数据结构之哈夫曼树

1.哈夫曼树简介

(1) WPL = 7*2+5*2+2*2+4*2 = 36

 

(1) WPL = 7*1+5*2+2*3+4*3 = 35;经过证明此为最小的WPL即为哈夫曼树

在解决某些问题时,利用哈夫曼树可以找到最佳判定算法,因为某些条件出现的频率不一样,这样导致了同一段代码在不同的环境下取得的效果不是最优的。

2. 哈夫曼树的构造算法

假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1w2wn,则哈夫曼树的构造规则为:

  (1) w1w2wn看成是有棵树的森林(每棵树仅有一个结点)

(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;

  (3)从森林中删除选取的两棵树,并将新树加入森林;

(4)重复(2)(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

构造过程如下:

(a) 有权值为1,2,3,4四棵树;

(b) 由于树1,2的权值处于最小和次最小,所以选中,并合成为一棵树,小的权值位于左边;

(c) 3,4,(1,2 = 3)三棵树里面选择权值最小的和次小的,我们选中3和(1,2

合成新树(3,(1,2= 6);

(d) 最后选出新树(4,(3,(1, 2)))

 

(来自:http://baike.baidu.com/view/127820.htm

3. 哈夫曼树具体实现

需要考虑的问题:

(1) 用什么样的存储结构;

(2) 怎么选择选择最小和次小权值的树;

(3) 怎么存放合成的新树

如果我们采用

Struct node

{

Int key;

Struct node *l;

Struct node *r;

}

的存储结构的话,可以采用数组的链式结构,并设计标记数组如下:

(我们以4个初始树为例子)

标记数组:(有则标记为1,否则为0

Struct node n1

Struct node n1

Struct node n1

Struct node n1

存储数组

Struct node n1

Struct node n1

Struct node n1

Struct node n1

第一次选择为1,2树,合成新树,我们可以统一放在最小树的位置上(也可以放在大树位置上),所以新树放于树的位置并更新其权值为两者之和,其状态为:

标记数组:(有则标记为1,否则为0

1

0

1

1

存储数组

Struct node n1

Free()

Struct node n1

Struct node n1

这样存储结构的问题解决了,其实做到这里我们应该比较清楚后面怎么做了,当然选择出最小值和次小值为比较简单的算法了。

例:设有8个字符{ABCDEFGH},其概率为{0.050.290.070.080.140.230.03,0.11},设其权值用整数表示为 {529781423311},其哈夫曼树如图1所示。

 

实现代码如下:

#include 

#include 

#include 

struct node 

{

int key;

struct node *l;

struct node *r;

};

typedef struct node *pnode;

int mark[100];

struct node  huffman[100];

void PrintNode(const pnode node)

{

printf("key = %d \n", node->key);

}

void PreOrder(pnode T)

{

if(T)

   {

   PrintNode(T);

   PreOrder(T->l);        

   PreOrder(T->r);

    }

  

}

void Select(int *mark, struct node *huffman, int size, int *choose)  

    int i; 

    for(i = 0; i< size; i++)

{

if(mark[i])

{

choose[0] = i;

i++;

break;

}

}

choose[1] = choose[0];

    for(;i < size;i++) 

    { 

        if(mark[i]) 

        { 

            if(huffman[choose[0]].key >= huffman[i].key) 

            { 

            choose[1] = choose[0];

                choose[0] = i; 

            } 

            else if(huffman[choose[1]].key > huffman[i].key)    choose[1] = i; 

        } 

    } 

void Choose(int *mark, struct node *huffman, int size, int *choose)

{

int i;

int minkey = 0;

int tkey = 0;

int temp = 0;

for(i = 0; i< size; i++)

{

if(mark[i])

{

minkey = i;

i++;

break;

}

}

tkey = minkey;

for(; i< size; i++)

{

if(mark[i])

{

if(huffman[i].key < huffman[minkey].key)

{

tkey = minkey;

minkey = i;

}

if(tkey == minkey)

tkey = i;

if(huffman[tkey].key > huffman[i].key && i != minkey)

{

tkey = i;

}

}

}

choose[0] = minkey;

choose[1] = tkey;

}

pnode HuffmanTree(int *mark, struct node *huffman, int size)

{

int choose[2];

int i;

pnode mynode; 

for(i = 0; i < size-1; i++)

{

Select(mark, huffman, size, choose);

mynode = (pnode)malloc(sizeof(struct node));

mynode->key = huffman[choose[0]].key+huffman[choose[1]].key;//更新key

mynode->l = (pnode)malloc(sizeof(struct node));

mynode->l->key = huffman[choose[0]].key;

mynode->l->l = huffman[choose[0]].l;

mynode->l->r = huffman[choose[0]].r;

mynode->r = &huffman[choose[1]];

huffman[choose[0]] = *mynode;

mark[choose[1]] = 0;

free(mynode);

return &huffman[choose[0]];

}

int main(void)

{

int key[8] = {5,29,7,8,14,23,3,11};

int i;

pnode huffmantree;

memset(mark, -1, sizeof(mark));

memset(huffman, 0, sizeof(huffman));

for(i = 0; i < 8; i++)

{

huffman[i].key = key[i];

}

huffmantree = HuffmanTree(mark, huffman, 8);

PreOrder(huffmantree);

return 0;

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值