C++创建一棵哈夫曼树以及输出其哈夫曼编码-创新互联

#includeusing namespace std;


class HufTree{public:
    float weight = 0;   // 权重
    int parent = 0;     // 双亲
    int lchi = 0;       // 左孩子
    int rchi = 0;       // 右孩子
        
    void CreatHT(HufTree* &HT, int n);  // 创建哈夫曼树方法
    void Select(HufTree* &HT, int k, int &s1, int &s2); // 得到权重最小的次小的下标方法
    char** Code(HufTree* HT, int n);    //实现哈夫曼编码方法
};


void HufTree::CreatHT(HufTree* &HT, int n){int s1, s2;     // 声明权重最小的下标s1和次小的下标s2
    HT = new HufTree[2 * n];    // 定义数组长度,0号位置不用,所以数组长度定义为2n-1+1,2n+1为最终哈夫曼树的总结点数
    // 输入每个结点的权重
    for(int i = 1; i< n + 1; ++i){cout<< "请输入第 "<< i<< " 个结点的权重值:"<< endl;
        cin >>HT[i].weight;
    }

    for(int i = n + 1; i< 2 * n; ++i){Select(HT, i - 1, s1, s2);      // 选出权重最小的两个结点
        HT[i].weight = HT[s1].weight + HT[s2].weight;   // 结合两个小结点得到一个新结点
        HT[i].lchi = s1;    // 新结点的左孩子为s1
        HT[i].rchi = s2;    // 新结点的有孩子为s2
        HT[s1].parent = i;  // s1的双亲是i
        HT[s2].parent = i;  // s2的双亲是i
    }
}


void HufTree::Select(HufTree* &HT, int k, int &s1, int &s2){// k为已有结点的长度加1(因为0号位置未使用)
    float t = 100;  // 初始化一个常数t
    // 通过比较得出s1
    for(int i = 1; i< k + 1; ++i){if(t >HT[i].weight && HT[i].parent == 0){s1 = i;
            t = HT[i].weight;
        }
    }
    t = 100;    // 重新初始化t
    // 通过跳过s1比较得到s2
    for(int i = 1; i< k + 1; ++i){if(i == s1) continue;
        if(t >= HT[i].weight && HT[i].parent == 0){s2 = i;
            t = HT[i].weight;
        }
    }
}


char** HufTree::Code(HufTree* HT, int n){char** HC = new char* [n + 1];  // 声明一个二维字符数组,用以接收原数组需要编码的字符的编码
    char* cd = new char[n];     // 声明一个一维字符数组用以储存
    cd[n - 1] = '\0';   // cd数组的最后一位加上终止符
    // 遍历原数组需要编码的每个字符
    for(int i = 1; i< n + 1; ++i){int j = i;  // j用于在while循环内实现从叶子结点找双亲
        int k = n - 2;  // k用于记录当前cd数组空的位置,由于从叶子结点找双亲的话编码顺序是反的,所以要从尾部开始存入0和1
        while(HT[j].parent != 0){// 若当前结点的双亲为0,说明已遍历到根结点,遍历完毕
            // 若该叶子的双亲结点的左孩子为该叶子结点,则cd数组计入0
            if(HT[HT[j].parent].lchi == j){cd[k] = '0';
                --k; // k指向cd数组的前一个位置
            }
            // 若该叶子的双亲结点的右孩子为该叶子结点,则cd数组计入1
            if(HT[HT[j].parent].rchi == j){cd[k] = '1';
                --k; // k指向cd数组的前一个位置
            }
            j = HT[j].parent;   // 此时遍历的结点更新为当前结点的双亲
        }
        HC[i] = new char[n - k];    // 申请一个和当前cd数组一样大小的字符数组,另二维数组中的第i个一维数组指针指向该字符数组
        strcpy(HC[i], &cd[k + 1]);  // 将cd中包括k从k之后的所有字符复制给HC的第i个字符数组
    }
    delete [] cd;   // 释放掉cd数组的空间
    return HC;  // 返回HC二维指针
}


int main()
{HufTree *a;     // 实例化一个HufTree指针a

    a->CreatHT(a, 7);   // 调用a中的创建方法创建一棵哈夫曼树

    char** p = a->Code(a, 7);   // 实例化一个二维数组指针指向哈夫曼编码数组

    // 打印二维数组
    for(int i = 1; i< 8; ++i){for(int j = 0; j< 7; ++j){cout<< p[i][j];
        }
        cout<< endl;
    }

    delete a;   // 释放掉a的空间

    // 释放掉二维数组p中的指针指向的空间
    for(int i = 0; i< 8; ++i){delete [] p[i];
    }

    delete [] p;    // 释放掉指向二维数组p的空间
    return 0;  
}

实现创建包含7个元素的哈夫曼树以及输出其对应的哈夫曼编码。如有错误的地方,还请不吝赐教。

创新互联建站凭借在网站建设、网站推广领域领先的技术能力和多年的行业经验,为客户提供超值的营销型网站建设服务,我们始终认为:好的营销型网站就是好的业务员。我们已成功为企业单位、个人等客户提供了网站设计制作、网站设计服务,以良好的商业信誉,完善的服务及深厚的技术力量处于同行领先地位。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前名称:C++创建一棵哈夫曼树以及输出其哈夫曼编码-创新互联
文章路径:http://scjbc.cn/article/gooec.html

其他资讯