贪心法求解Huffman编码

一、Huffman编码
1、问题描述
设要编码的字符集为{d1, d2, …, dn},它们出现的频率为{w1, w2, …, wn},应用哈夫曼树构造最优的不等长的由0、1构成的编码方案。
2、问题求解
在这里插入图片描述
在这里插入图片描述
3、举例
在这里插入图片描述
4、算法设计

int n;
struct HTreeNode   //哈夫曼树结点类型
{  char data;    //字符
   int weight;    //权值
   int parent;    //双亲的位置
   int lchild;    //左孩子的位置
   int rchild;    //右孩子的位置
};
HTreeNode ht[MAX];   //存放哈夫曼树
map<char,string> htcode;  //存放哈夫曼编码
struct NodeType   //优先队列结点类型
{  int no;    //对应哈夫曼树ht中的位置
   char data;    //字符
   int  weight;   //权值
   bool operator<(const NodeType &s) const
   {     //用于创建小根堆
 return s.weight<weight;
   }
};
void CreateHTree()   //构造哈夫曼树
{  NodeType e,e1,e2;
   priority_queue<NodeType> qu;
   for (int k=0;k<2*n-1;k++)  //设置所有结点的指针域
      ht[k].lchild=ht[k].rchild=ht[k].parent=-1;
   for (int i=0;i<n;i++)  //将n个结点进队qu
   {  e.no=i; e.data=ht[i].data;
      e.weight=ht[i].weight; qu.push(e);
   }
   for (int j=n;j<2*n-1;j++)  //构造哈夫曼树的n-1个非叶子结点
   {  e1=qu.top();  qu.pop();  //出队权值最小的结点e1
      e2=qu.top();  qu.pop();  //出队权值次小的结点e2
      ht[j].weight=e1.weight+e2.weight; //构造哈夫曼树的非叶子结点j 
      ht[j].lchild=e1.no;
      ht[j].rchild=e2.no;
      ht[e1.no].parent=j;  //修改e1.no的双亲为结点j
      ht[e2.no].parent=j;  //修改e2.no的双亲为结点j
      e.no=j;    //构造队列结点e
      e.weight=e1.weight+e2.weight;
      qu.push(e);
   }
}
void CreateHCode()        //构造哈夫曼编码
{  string code;
   code.reserve(MAX);
   for (int i=0;i<n;i++)       //构造叶子结点i的哈夫曼编码
   {  code="";
      int curno=i;
      int f=ht[curno].parent;
      while (f!=-1)        //循环到根结点
      {  if (ht[f].lchild==curno)  //curno为双亲f的左孩子
            code='0'+code;
         else         //curno为双亲f的右孩子
            code='1'+code;
         curno=f; f=ht[curno].parent;
      }
      htcode[ht[i].data]=code;     //得到ht[i].data字符的哈夫曼编码
   }
}

5、算法证明
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
6、算法分析
上述算法采用了小根堆,因为从堆中删除两个结点(权值最小的两个二叉树根结点)和加入一个新结点的时间复杂度是O(log2n),这样修改后构造哈夫曼树算法的时间复杂度为O(nlog2n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值