数据结构-哈夫曼编码

 


#include<iostream>
#include<algorithm>
using namespace std;

typedef int WeightType;
typedef char ElementType;

/*哈夫曼树的定义*/
typedef struct HuffmanNode *PtrToHuffmanNode;
struct HuffmanNode{
    ElementType Element = '0';//存储编码的字母:0表示不是叶结点
    int Weight;//储存哈夫曼树结点的频率值
    PtrToHuffmanNode Left = NULL;//指向左孩子的指针
    PtrToHuffmanNode Right = NULL;//指向右孩子的指针
};
typedef PtrToHuffmanNode Huffman;//哈夫曼树

/*最小堆定义*/
typedef struct HeapNode *Heap;
struct HeapNode{
    Huffman HuffArr;   //用来存储哈夫曼树指针的数组
    int Size;          //堆中当前元素个数
    int Capacity;      //堆的最大容量
};
typedef Heap MinHeap; //最小堆

#define MINDATA 0 //该值需要小于堆中所有可能元素的值
#define MAXSIZE 640 //最大堆结点=最大哈夫曼树结点+1

/*编码结果结构体定义*/
struct CodeResult{
    ElementType Element;
    WeightType Weight;
    string code;
    int Ncode = 0;
}AllCodeResult[MAXSIZE];
int IndexC=0;

bool IsFull(MinHeap MinH)
{
    return (MinH->Size == MinH->Capacity);
}

bool IsEmpty(MinHeap MinH)
{
    return (MinH->Size == 0);
}

MinHeap Create(int MaxSize)
{
    MinHeap MinH = new HeapNode;
    MinH->HuffArr = new HuffmanNode [MaxSize + 1];
    MinH->Size = 0;
    MinH->Capacity = MaxSize;

    MinH->HuffArr[0].Weight = MINDATA;

    return MinH;
}

void Insert(MinHeap MinH, HuffmanNode Huff)
{
    int i = 0;
    if(IsFull(MinH)){
        cout << "MinHeap is full" <<endl;
        return;
    }
    i = ++MinH->Size;
    for(; MinH->HuffArr[i/2].Weight > Huff.Weight; i/=2){
        MinH->HuffArr[i] = MinH->HuffArr[i/2];
    }
    MinH->HuffArr[i] = Huff;
}

Huffman DeleteMin(MinHeap MinH)
{
    int Parent, Child;
    Huffman MinHuffman;
    HuffmanNode temp;

    if(IsEmpty(MinH)){
        cout << "MinHeap is empty!" << endl;
        return NULL;
    }
    MinHuffman = new HuffmanNode;
    *MinHuffman = MinH->HuffArr[1];

    temp = MinH->HuffArr[MinH->Size--];
    for(Parent = 1; Parent*2 <= MinH->Size; Parent = Child){
        Child = Parent * 2;
        if((Child != MinH->Size) && \
            (MinH->HuffArr[Child].Weight > MinH->HuffArr[Child+1].Weight))
            ++Child;
        if(temp.Weight <= MinH->HuffArr[Child].Weight) break;
        else
            MinH->HuffArr[Parent] = MinH->HuffArr[Child];
    }
    MinH->HuffArr[Parent] = temp;

    return MinHuffman;
}

Huffman BuildHuffman(MinHeap MinH)
{
    Huffman NewHuffman;
    int N = MinH->Size;

    for(int i=1; i<N; i++)
    {
        NewHuffman = new HuffmanNode;
        NewHuffman->Left = DeleteMin(MinH);
        NewHuffman->Right = DeleteMin(MinH);
        NewHuffman->Weight = NewHuffman->Left->Weight + NewHuffman->Right->Weight;
        Insert(MinH, *NewHuffman);
    }
    NewHuffman = DeleteMin(MinH);

    return NewHuffman;
}



void EnCode(Huffman HuffRoot, string code[], int i)
{
    //递归出口:找到叶结点,其Element是要求的字母
    if(HuffRoot->Left == NULL && HuffRoot->Right == NULL){
        string CurrCode = code[0];
        AllCodeResult[IndexC].Ncode = 1;
        for(int n=1; n<i; n++){
            CurrCode += code[n];
            AllCodeResult[IndexC].Ncode += 1;
        }
        AllCodeResult[IndexC].code = CurrCode;
        AllCodeResult[IndexC].Element = HuffRoot->Element;
        AllCodeResult[IndexC].Weight = HuffRoot->Weight;
        IndexC += 1;
        return;
    }
    code[i] = "0";
    EnCode(HuffRoot->Left, code, i+1);

    code[i] = "1";
    EnCode(HuffRoot->Right, code, i+1);
}


int main()
{
    int N, M, AllBitNum;;
    MinHeap MinH;
    HuffmanNode Huff;
    Huffman HuffmanRoot;

    //初始化最小堆
    MinH = Create(MAXSIZE);

    //输入字符个数
    cin >> N;
    ElementType AllElement[N];
    WeightType AllWeight[N];//字符对应的频率值数组
    /*举例
    WeightType AllWeight[N] = {1,1,1,3,3,6,6};
    ElementType AllElement[N] = {'A','B','C','D','E','F','G'};
    */

    //通过输入构建最小堆-实现对字符频率值的排序
    for(int i=0; i<N; i++){
        cin >> AllElement[i]; //读取输入字符
        cin >> AllWeight[i]; //读取输入字符的频率值
        Huff.Element = AllElement[i];
        Huff.Weight = AllWeight[i];
        Insert(MinH, Huff); //将其哈夫曼结点插入到最小堆
    }

    //根据最小堆构建哈夫曼树
    HuffmanRoot = BuildHuffman(MinH);

    string code[N];
    //获得哈夫曼编码
    EnCode(HuffmanRoot, code, 0);

    for(int i=0; i<N; i++){
        cout << AllCodeResult[i].Element << " ";
        cout << AllCodeResult[i].code <<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值