/*
【问题描述】已知输入一串正整数,正整数之间用空格键分开,请建立一个哈夫曼树,以输入的数字为叶节点,求这棵哈夫曼树的带权路径长度。【输入形式】首先输入正整数的个数,然后接下来为接下来的正整数,正整数个数不超过10个【输出形式】输出相应的权值【样例输入】5 4 5 6 7 8【样例输出】69
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int data;
struct Node *leftchild,*rightchild;
}BNode,*BTree;
// 本题建立堆优化,使得每次提取元素时复杂度都为O(1),顺便练习一下堆的实现
int len;
BTree heap[20];
void swap(BTree *a,BTree *b)
{
BTree tmp=*a;
*a=*b;
*b=tmp;
}
void push_heap(BTree *heap,BTree s)
{
heap[++len]=s;
int t=len;
while (t>1)
{
if (heap[t>>1]->data>heap[t]->data)
{
swap(&heap[t>>1],&heap[t]);
}
else return;
}
}
BTree pop_heap(BTree *heap)
{
BTree re=heap[1],x;
heap[1]=heap[len--];
int m=len>>1,t=1,k;
while (t<=m)
{
k=t;
if (heap[t<<1]->data<heap[t]->data)
k=t<<1;
if ((t<<1)+1<=len)
if(heap[k]->data>heap[(t<<1)+1]->data)
k=(t<<1)+1;
if (k!=t)
{
swap(&heap[k],&heap[t]);
t=k;
}
else return re;
}
return re;
}
void heap_adjust(BTree *heap,int pos,int end)
{
int i;
BTree t=heap[pos];
for (i=2*pos;i<=end;i<<=1)
{
if (i<end && heap[i]->data<heap[i+1]->data)
++i;
if (heap[pos]->data>heap[i]->data) break;
heap[pos]=heap[i];
pos=i;
}
heap[pos]=t;
}
void sort_heap(BTree *heap)
{
int i;
BTree t;
for (i=len/2;i>0;i--)
heap_adjust(heap,i,len);
for (i=len;i>1;i--)
{
swap(&heap[1],&heap[i]);
heap_adjust(heap,1,i-1);
}
}
int main()
{
BTree root,lchild,rchild;
scanf("%d",&len);
int i;
int ans=0;
for (i=1;i<=len;++i)
{
heap[i]=(BTree)malloc(sizeof(BNode));
scanf("%d",&heap[i]->data);
}
sort_heap(heap); // Creat Heap
while (len>1)
{
lchild=pop_heap(heap);
rchild=pop_heap(heap);
root=(BTree)malloc(sizeof(BNode)); //Pop two BTree and Mix Up
root->data=lchild->data+rchild->data;
ans+=root->data;
root->leftchild=lchild;
root->rightchild=rchild;
push_heap(heap,root);
}
root=pop_heap(heap); //Find the Root of the tree
printf("%d\n",ans); //Output
//system("pause");
}