Huffman

概念

路径长度: 树中从一个结点到另一个结点之间的分支数目。
树的路径长度: 树根到每一个结点的路径长度之和。
结点的带权路径长度: 从结点到树根之间的路径长度与结点上权的乘积。
树的带权路径长度: 树中所有叶子结点的带权路径长度之和。
W P L = ∑ k = 1 n w k l k WPL= \sum_{k=1}^{n}{w_{k}l_{k}} WPL=k=1nwklk
最优二叉树(哈夫曼树): WPL最小的二叉树

哈夫曼算法

( 1 ) 根 据 给 定 的 n 个 权 值 { w 1 , w 2 , . . . , w n } 构 成 二 叉 树 集 合 F = { T 1 , T 2 , . . . T n } (1)根据给定的n个权值\{w_{1},w_{2},...,w_{n}\}构成二叉树集合F=\{T_{1},T_{2},...T_{n}\} (1)n{w1,w2,...,wn}F={T1,T2,...Tn}
(2)在F中选取权值最小的两棵二叉树构成新的二叉树,并更新新二叉树的权值。
(3)在F中删除这两棵二叉树,并将新二叉树放入F中。
(4)重复(2)、(3)步直至只剩下一棵二叉树,即哈夫曼树。

数据结构

链表型

typedef struct HTCode{
 char ch;//元素
 int weight;//权重
 HTCode* lChild, * rChild;//左右子树
 bool isLeaf;//是否为叶子结点
}HTCode,*HuffmanTree;

由二叉树堆构建哈夫曼树

输入

 HuffmanTree* heap;
 cin >> N;
 heap = new HuffmanTree[N];
 weight = new int[N];
 for (i = 0; i < N; i++)
  heap[i] = new HTCode;
 for (i = 0; i < N; i++)
 {
  cin >> heap[i]->ch >> heap[i]->weight;
  heap[i]->lChild = NULL;
  heap[i]->rChild = NULL;
 }

从树堆中获取最小树

HuffmanTree GetMinTree(HuffmanTree* heap, int n)//从树堆中获取最小树
{
 int minPos = 0, i;
 HuffmanTree minTree = heap[0];
 for (i = 0; i < n; i++)
  if (heap[i]->weight < minTree->weight)
  {
   minTree = heap[i];
   minPos = i;
  }
 for (i = minPos; i < n - 1; i++)
  heap[i] = heap[i + 1];
 return minTree;
}

构建哈夫曼树

HuffmanTree GetHuffmanTree(HuffmanTree* heap, int n)//由根节点树建立哈夫曼树
{
 if (n == 1) return heap[0];
 HuffmanTree min1, min2, newMin;
 min1 = GetMinTree(heap, n);
 min2 = GetMinTree(heap, n - 1);
 newMin = new HTCode;
 newMin->weight = min1->weight + min2->weight;
 newMin->lChild = min1;
 newMin->rChild = min2;
 heap[n - 2] = newMin;
 GetHuffmanTree(heap, n - 1);
}

获取哈夫曼树带权路径长度

int GetMinLength(HuffmanTree ht,int depth)//获取哈夫曼树带权路径长度
{
 if (!ht->lChild && !ht->rChild)
  return ht->weight * depth;
 else
  return GetMinLength(ht->lChild, depth + 1) + GetMinLength(ht->rChild, depth + 1);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值