# include <iostream>
using namespace std ;
typedef struct
{
unsigned int weight ; //节点的权值
unsigned int parent ;
unsigned int lchild ;
unsigned int rchild ;
}HTNode,*HuffmanTree;
//typedef char** HuffmanCode ;
void InitHuffmanTree(HuffmanTree & ,int );
void Select(HuffmanTree HT ,int n,int & s1,int & s2);
int Min_Weight(HuffmanTree HT ,int n );
void InitHuffmanTree(HuffmanTree & HT ,int n);
void HuffmanCoding(HuffmanTree & HT , int n);
int Weight_Length(HuffmanTree HT , int n);// 计算带权路径长度
int Find_length(HuffmanTree HT ,int n);// 计算每个叶子节点到根节点的路径长度
int main(void)
{
int datanum ; // 数据的组数
scanf ("%d",&datanum);
while (datanum)
{
HuffmanTree HT;
int n ; // 每组数据的个数
scanf("%d",&n);
InitHuffmanTree(HT,n); // 初始化哈弗曼树为编码做准备
HuffmanCoding(HT,n); // 开始编码
/*for (int i = 1; i <= 2*n-1 ; i ++) // 此处用于查看内存中的值,检查编码是否正确
{
printf ("%5d%5d%5d%5d%5d\n",i,HT[i].weight ,HT[i].lchild ,HT[i].rchild ,HT[i].parent);
}
*/
printf("%d\n",Weight_Length(HT,n));
datanum -- ;
}
return 0 ;
}
int Weight_Length(HuffmanTree HT , int n)
{
int len = 0 ;
while (n)
{
len = len + Find_length(HT,n) * HT[n].weight ;
n -- ;
}
return len ;
}
// 因为从根节点到叶子的路径长度不好找,难以确定走的方向,此处才用的是从叶子到根节点走的方式,每走一步记下,更新长度
int Find_length(HuffmanTree HT ,int n)
{
int distance = 0 ;
int f ;
for (f = HT[n].parent ;f != 0 ; f = HT[f].parent)
{
distance ++ ;
}
return distance ;
}
void HuffmanCoding(HuffmanTree & HT , int n)
{
int m = 2 * n - 1 ;
for (int i = n + 1 ; i <= m ; i ++)
{
int s1,s2;
Select(HT,i-1,s1,s2); // 在HT中选择两个权值parent为0的相对较小的元素,返回的值中满足s1>=s2的关系
HT[s1].parent = i ;
HT[s2].parent = i ;
HT[i].lchild = s1 ;
HT[i].rchild = s2 ;
HT[i].weight = HT[s1].weight + HT[s2].weight ;
}
return ;
}
// 找到两个相对较小的元素并返回
void Select(HuffmanTree HT ,int n,int & s1,int & s2)
{
s1 = Min_Weight(HT,n);
s2 = Min_Weight(HT,n);
return ;
}
int Min_Weight(HuffmanTree HT ,int n ) // 找到相对小的元素并将其标记以表示将其从集合中删去
{
unsigned int k = 1000 ;
unsigned int min = 0 ;
int i = 1;
while (i <= n )
{
if (!HT[i].parent && HT[i].weight < k)
{
k = HT[i].weight ;
min = i ;
}
i ++ ;
}
HT[min].parent = -1 ; // 标示找到的较小的元素的位置
return min;
}
void InitHuffmanTree(HuffmanTree & HT ,int n)
{
int m = 2*n-1;
HT = (HuffmanTree)malloc( (m+1) * sizeof(HTNode)); // 此处因为不用0号单元所以得多申请一块内存空间
if (!HT)
{
exit(-1);
}
for(int i = 1 ; i <= n ; i ++ )
{
scanf("%d",&HT[i].weight);
HT[i].lchild = 0;
HT[i].parent = 0;
HT[i].rchild = 0;
}
for (i = n + 1 ;i <= m ;i ++)
{
HT[i].lchild = 0 ;
HT[i].parent = 0 ;
HT[i].rchild = 0 ;
HT[i].weight = 0 ;
}
return ;
}