浙江大学的教材《数据结构》第146页上的用堆构建哈夫曼链表树的函数的实现
1. 函数结构与书中代码相同。堆中元素为指向哈夫曼树的节点的指针:
struct HuffmanTree
{
int weight;
HuffmanTree* left;
HuffmanTree* right;
};
struct MinHeap
{
HuffmanTree** data;
int size;
int capacity;
};
2. 建堆函数不变,删除堆顶元素和插入元素函数由原来的直接对各个节点的数据进行过滤改为对指向节点的指针的过滤。把堆的元素设置为指向节点的指针的好处有两个,一个是方便通过操作指针来实现数据的插入和删除,另一个是可以构成链表把整个哈夫曼树连接起来。
3. 最后通过层序遍历输出哈夫曼树。
#include <stdio.h>
#include <malloc.h>
#include <cmath>
struct HuffmanTree
{
int weight;
HuffmanTree* left;
HuffmanTree* right;
};
HuffmanTree* CreateHuffman()
{
HuffmanTree* huffman = (HuffmanTree*) malloc(sizeof(HuffmanTree));
huffman->weight = 0;
huffman->left = NULL;
huffman->right = NULL;
return huffman;
}
struct MinHeap
{
HuffmanTree** data;
int size;
int capacity;
};
const int MINSIZE = -1;
MinHeap* CreateMinHeap(int maxSize)
{
MinHeap* heap = (MinHeap*) malloc(sizeof(MinHeap));
heap->data = (HuffmanTree**) malloc(sizeof(HuffmanTree*) * (maxSize + 1));
for (int i = 0; i <= maxSize; i++)
{
heap->data[i] = (HuffmanTree*) malloc(sizeof(HuffmanTree));
heap->data[i]->left = NULL;
heap->data[i]->right = NULL;
heap->data[i]->weight = 0;
}
heap->size = 0;
heap->capacity = maxSize;
heap->data[0]->weight = MINSIZE;
return heap;
}
MinHeap* BuildMinHeap(MinHeap* heap)
{
// 这里假设所有H->size个元素已经存在H->data[]->weight中
int i = heap->size / 2;
int parent = i;
int child = 0;
int temp = 0;
for (; i > 0; i--)
{
temp = heap->data[i]->weight;
for (parent = i; parent * 2 <= heap->size; parent = child)
{
child = parent * 2;
if ((child != heap->size) && (heap->data[child]->weight > heap->data[child + 1]->weight))
{
child++;
}
if (temp <= heap->data[child]->weight)
{
break;
}
else
{
heap->data[parent]->weight = heap->data[child]->weight;
}
}
heap->data[parent]->weight = temp;
}
return heap;
}
HuffmanTree* DeleteMinHeap(MinHeap* heap)
{
if (heap->size == 0)
{
printf("Heap is EMPTY.\n");
return NULL;
}
HuffmanTree* const lastNode = heap->data[heap->size];
heap->size--;
HuffmanTree* const deletedNode = heap->data[1];
int parent = 1;
int child = 2;
for (; parent * 2 <= heap->size; parent = child)
{
child = parent * 2;
if (child != heap->size && heap->data[child]->weight > heap->data[child + 1]->weight)
{
child++;
}
if (lastNode->weight > heap->data[child]->weight)
{
heap->data[parent] = heap->data[child];
}
else
{
break;
}
}
heap->data[parent] = lastNode;
return deletedNode;
}
void InsertMinHeap(MinHeap* heap, HuffmanTree* huffman)
{
if (heap->size == heap->capacity)
{
printf("Heap is FULL.\n");
return;
}
int item = huffman->weight;
heap->size++;
int i = heap->size;
for(; heap->data[i / 2]->weight > item; i /= 2)
{
heap->data[i] = heap->data[i / 2];
}
heap->data[i] = huffman;
}
void BuildHuffman(MinHeap* heap)
{
HuffmanTree* huffman;
BuildMinHeap(heap);
const int SIZE = heap->size;
for (int i = 1; i < SIZE; i++)
{
huffman = CreateHuffman();
huffman->left = DeleteMinHeap(heap);
huffman->right = DeleteMinHeap(heap);
huffman->weight = huffman->left->weight + huffman->right->weight;
InsertMinHeap(heap, huffman);
}
}
typedef HuffmanTree* QueueType;
struct QNode
{
QueueType data;
QNode* next;
};
struct LinkQueue
{
QNode* rear;
QNode* front;
};
bool IsEmptyQ(LinkQueue* queue)
{
return (queue->front == NULL);
}
LinkQueue* CreateQueue()
{
LinkQueue* queue = (LinkQueue*) malloc(sizeof(LinkQueue));
queue->front = NULL;
queue->rear = NULL;
return queue;
}
void AddQ(LinkQueue* p, QueueType const item)
{
if (p->front == NULL)
{
QNode* newNode = (QNode*) malloc(sizeof(QNode));
newNode->data = item;
newNode->next = NULL;
p->front = newNode;
p->rear = newNode;
return;
}
QNode* newNode = (QNode*) malloc(sizeof(QNode));
newNode->data = item;
newNode->next = NULL;
p->rear->next = newNode;
p->rear = newNode;
}
QueueType DeleteQ(LinkQueue* p)
{
if (p->front == NULL)
{
printf("Queue is empty.");
return NULL;
}
QNode* temp = p->front;
if (p->front == p->rear)
{
p->front = NULL;
p->rear = NULL;
QueueType item = temp->data;
free(temp);
return item;
}
p->front = p->front->next;
QueueType item = temp->data;
free(temp);
return item;
}
int main(void)
{
MinHeap* testHeap = CreateMinHeap(5);
for(int i = 1; i <= 5; i++)
{
testHeap->data[i]->weight = abs(10 * sin(i * i));
testHeap->size++;
}
BuildHuffman(testHeap);
LinkQueue* queue = CreateQueue();
AddQ(queue, testHeap->data[1]);
HuffmanTree* tempNode = NULL;
while (!IsEmptyQ(queue))
{
tempNode = DeleteQ(queue);
printf("%d ", tempNode->weight);
if (tempNode->left != NULL)
{
AddQ(queue, tempNode->left);
}
if (tempNode->right != NULL)
{
AddQ(queue, tempNode->right);
}
}
return 0;
}