数据结构-哈夫曼树编码的输出(2)接上篇博文

来源:互联网 发布:山东大学双一流 知乎 编辑:程序博客网 时间:2024/06/15 10:51
/*
 *Date: 17-11-28
 *Author: Qian_Yu
 *Program: 哈夫曼树编码的输出
 */
#include <iostream>
#include <string.h>
using namespace std;
typedef struct node {
    int weight;
    int parent,lchild,rchild;
} *HfmTree;
typedef char **HfmCode;//储存哈夫曼树编码的一维动态字符空间定义
static int s1 = 1,s2 = 1;
void createHfmTree(HfmTree &hf,int *w,int n);
void select(HfmTree hf,int n);
void createHfmCode(HfmTree hf,HfmCode &hc,int n);
int main() {
    int w[] = {5,29,7,8,14,23,3,11};
    HfmTree hf;
    int n = sizeof(w) / sizeof(w[0]);
    createHfmTree(hf,w,n);
    cout << "哈夫曼树创建成功,它的最小带权路径长度为:" << hf[2 * n - 1].weight << endl;
    HfmCode hc;
    createHfmCode(hf,hc,n);
    cout << "它满足的哈夫曼编码为:\n";
    for(int i = 1;i <= n;i++) {
        cout << hc[i] << endl;
    }
    return 0;
}
//哈夫曼树的创建
void createHfmTree(HfmTree &hf,int *w,int n) {
    if(n <= 1) {
        return;
    }
    int m = 2 * n - 1;
    hf = new node[m + 1];
    for(int i = 1;i <= m;i++) {//把前m个单元数据值初始化为0
        hf[i].parent = 0;
        hf[i].lchild = 0;
        hf[i].rchild = 0;
    }
    for(int i = 1;i <= n;i++) {//给前n个单元数据赋权值
        hf[i].weight = w[i - 1];
    }
    for(int i = n + 1;i <= m;i++) {//更新新节点
        select(hf,i - 1);
        hf[s1].parent = i;
        hf[s2].parent = i;
        hf[i].lchild = s1;
        hf[i].rchild = s2;
        hf[i].weight = hf[s1].weight + hf[s2].weight;
    }
}
//每次在已更新的新树中拿出两个最小权的下标
void select(HfmTree hf,int n){
    int i = 1;
    while(hf[i].parent != 0) i++;//在已更新的树中找出第一个元素的下标
    s1 = i;
    for(int j = i + 1;j <= n;j++) {//找出已更新的树中第一个最小权值的下标
        if(hf[j].parent == 0 && hf[j].weight < hf[s1].weight) {
            s1 = j;
        }
    }
    hf[s1].parent = -1;
    while(hf[i].parent != 0) i++;//在已更新的树中找出第二个元素的下标
    s2 = i;
    for(int j = i + 1;j <= n;j++) {//找出已更新的树中第二个最小权值的下标
        if(hf[j].parent == 0 && hf[j].weight < hf[s2].weight) {
            s2 = j;
        }
    }
    hf[s2].parent = -1;
}
//哈夫曼编码的递推
void createHfmCode(HfmTree hf,HfmCode &hc,int n) {
    int f,c,start;
    hc = new char*[n + 1];//开辟n+1个足够的空间
    char* cd = new char[n];//开辟储存一个字符编码的临时空间
    cd[n - 1] = '\0';//置结束节点
    for(int i = 1;i <= n;i++) {//遍历每个权节点置根
        start = n - 1;
        c = i;
        f = hf[i].parent;
        while(f != 0) {
            start--;
            if(hf[f].lchild == c) {
                cd[start] = '0';
            }
            else {
                cd[start] = '1';
            }
            c = f;
            f = hf[f].parent;
        }
        hc[i] = new char[n - start];//把含有字符的空间赋值到储存哈夫曼编码的一维动态空间
        strcpy(hc[i],&cd[start]);
    }
    delete cd;
}