background:(1)所有节点放入集合k中

         (2)k中剩余节点大于两个时,取出权值最小的两个节点,构建他们为某个新节点的左右子节点,该新节点的权值为子节点权值的和,将该新节点加入k集合中

          (3)若k中只剩下一个节点,则该节点即为构造出的哈夫曼树的根节点,所有非终端节点的权值和就是该Huffman树的带权路径和。

注:此处为从K中取出两个权值最小的两个节点,需要用到堆,而堆是数据结构中一种重要的结构,读者可以自行了解,它可以以o(logn)时间复杂度取出最小元素,而标准模板库中有--优先队列。利用语句:priority_queue<int> Q;但默认是大顶堆,我们需要使用小顶堆,因此用 如下语句:priority_queue<int, vector<int>,greater<int>> Q;关于堆的操作如下:Q.push(x);//将元素放入堆中。Q.pop();//取出堆顶元素最小元素保存在a中。弹出堆顶元素后会自动调整为一个新的小顶堆。它的使用在之前使用过的队列一样的标准模板库queue中,所以在使用它之前我们必须做相应预处理。

#include<queue>

using namespace std;

issue:Huffman树,第一行输入一个数n,表示叶节点的个数,需要用这些叶节点生成Huffman树,根据Huffman树的概念,这些节点的所有权值,即weight,题目需要输出所有节点的值与权值的乘积之和。

输入:5

          1 2 2 5 9

输出:37

source:北京邮电大学计算机研究生机试真题

code:

#include<stdio.h>
#include<queue>
using namespace std;
priority_queue<int,vector<int>,greater<int> > Q;//建立小顶堆*****此处的‘> >’之间的空格不可少否则报错
int main(){
    int n;
 while(scanf("%d",&n)!=EOF){//crtl+z会退出循环
  while(Q.empty()==false){
   Q.pop();//清空堆中元素
  }
  for(int i=1;i<=n;i++){
  int x;
  scanf("%d",&x);
  Q.push(x);
  }
  int ans=0;
  while(Q.size()>1){
  int a=Q.top();
  Q.pop();
  int b=Q.top();
  Q.pop();
  //取出堆中两个最小元素,他们为同一个节点的左右儿子,且该双亲节点的权值为他们的和
  ans+=a+b;//该父节点必为非叶子节点,固累加其权值**********emphasis:所有非终端节点求和,必定是Huffman树的带权路径长
  Q.push(a+b);//求和后重新压入堆中
  }
  printf("%d\n",ans);//输出答案
 }
 return 0;
}