#include<iostream>
#include< algorithm >
using namespace std;
struct MinTuple
{
int x;
int y;
};
struct HNode
{
int weight;
int parent;
int LChild;
int RChild;
};
struct HCode
{
char data;
string code;
};
class Huffman
{
private:
HNode* HTree;
HCode* HCodeTable;
int N;
void code(int i, string newcode);
int Tracing(int);
public:Huffman(int n);
void CreateHTree(int* a, int n, char name[]);
void CreateCodeTable();
void Decode(char* s, char* d);
int tot();
};
Huffman::Huffman(int n)
{
HTree = new HNode;
HCodeTable = new HCode;
N = n;
}
int Huffman::Tracing(int a)
{
int i = 0;
while (HTree[a].parent != -1)
{
a = HTree[a].parent;
i++;
}
return i;
}
int Huffman::tot()
{
int num = 0;
for (int i = 0; i < N; i++)
{
num += HTree[i].weight * Tracing(i);
}
return num;
}
MinTuple SelectMin(HNode* s, int start, int end)
{
/*
整体来看,我对自己写的这份取小代码还是很满意的,因为这里利用到了
Huffman树的构建过程的特点,就是已经使用过的数据的双亲节点会不再是-1
整体来讲问题不大,还有那两个赋值过程也比较聪明先赋值小的,如果不满足再看次小的*/
/*可以从chatgpt上学到很多
*/
MinTuple minimum = { -1,-1 };
for (int j = start; j < end; j++)
{
if (s[j].parent == -1)
{
if (minimum.x == -1 || s[j].weight < s[minimum.x].weight)
{
minimum.y = minimum.x;
minimum.x = j;
}
else if (minimum.y == -1 || s[j].weight < s[minimum.y].weight)
minimum.y = j;
}
}
return minimum;
}
void Huffman::CreateHTree(int* a, int n, char name[])
{
N = n;
HCodeTable = new HCode[N];
HTree = new HNode[2 * N - 1];
for (int i = 0; i < N; i++)
{
HTree[i].weight = a[i];
HTree[i].LChild = HTree[i].RChild = HTree[i].parent = -1;
HCodeTable[i].data = name[i];
}
//思考:目前 我需要从HTree的顺序表中每次挑选两个最小值,但是不能重复挑选
//怎么去实现呢?而且需要将获得的新值加入进去,并且将使用过的删去
//可以看他的双亲是否存在
MinTuple m;
for (int i = n; i < 2 * N - 1; i++)
{
m = SelectMin(HTree, 0, i);//自行实现 从1~i中选出权值最小的两个点
HTree[m.x].parent = HTree[m.y].parent = i;
HTree[i].weight = HTree[m.x].weight + HTree[m.y].weight;
HTree[i].LChild = m.x;
HTree[i].RChild = m.y;
HTree[i].parent = -1;
}
}
void Huffman::code(int i, string newcode)
{
if (HTree[i].LChild == -1)
{
HCodeTable[i].code = newcode;
return;
}
code(HTree[i].LChild, newcode + "0");
code(HTree[i].RChild, newcode + "1");
}
void Huffman::CreateCodeTable()
{
code(2 * N - 2, "");
}
void Huffman::Decode(char* s, char* d)
{
while (*s != '\0')
{
int parent = 2 * N - 2;
while (HTree[parent].LChild != -1)
{
if (*s == '0')
{
parent = HTree[parent].LChild;
}
else
{
parent = HTree[parent].RChild;
}
s++;
}
*d = HCodeTable[parent].data;
d++;
}
}
int main()
{
int b = 0;
cin >> b; Huffman a(b);
int c[100];
for (int i = 0; i < b; i++)
{
cin >> c[i];
}
char d[] = { 0 };
a.CreateHTree(c, b, d);
cout << a.tot();
}