閑著去逛論壇,看到有人問建huffman樹。記得當初學資料結構時我沒寫過,所以也來試試。不過這個當作業實在是太遲了:)
/**//*
做huffman用堆排序應該效率最高了吧,不過自己寫一個太麻煩,就直接用stl算了:
*/
#include cstdio>
#include vector>
#include algorithm>
template class Type >
struct node
{
node *left, *right;
int value;
const Type *data;
struct ptrcmp // 仿函數,用於堆排序的比較
{
bool operator () (const node* a, const node* b)
{
return a->value > b->value; // 最小堆
}
};
};
template class Type >
node Type >* buildHuffmanTree(const Type data[], int count)
{
typedef node Type > Node;
// 初始化堆
::std::vector Node* > heap(count, NULL);
heap.clear();
for(int i= 0; i count; i++)
{
Node *n = new Node;
n->left = NULL;
n->right = NULL;
n->data = &data[i];
n->value = data[i]; // 如果Type不能轉化到int,則必須重載一個operator int()
heap.push_back(n);
}
::std::make_heap(heap.begin(), heap.end(), Node::ptrcmp());
// 用堆排序找到最小的2個元素,建立它們的父節點
while(heap.size() > 1)
{
Node *n1, *n2, *t;
::std::pop_heap(heap.begin(), heap.end(), Node::ptrcmp());
n1 = heap.back();
heap.pop_back();
::std::pop_heap(heap.begin(), heap.end(), Node::ptrcmp());
n2 = heap.back();
t = new Node; // 父節點
t->left = n1;
t->right = n2;
t->value = n1->value + n2->value; // 權值為孩子們權的和
// 再把這個父節點放回堆
heap.back() = t;
::std::push_heap(heap.begin(), heap.end(), Node::ptrcmp());
}
return heap.front();
}
template class Type >
void destoryTree(node Type >* root)
{
if (root->left) destoryTree(root->left);
if (root->right) destoryTree(root->right);
delete root;
}
template class Type >
void drawTree(node Type >* root)
{
printf("%d",root->value);
if (root->left)
{
printf("(");
drawTree(root->left);
printf(",");
}
if (root->right)
{
drawTree(root->right);
printf(")");
}
}
// 測試案例
int main()
{
int data[] = {2,3,4,5,1,2,3,65,8,2,};
node int > *root = buildHuffmanTree(data, sizeof(data)/sizeof(data[0]));
drawTree(root); // 結果為:95(30(13(6(3,3),7(3(1,2),4)),17(8,9(4(2,2),5))),65)
printf("\n");
destoryTree(root);
return 0;
}