C++ 链表实现构造Huffman树

浙江大学的教材《数据结构》第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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值