版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
#pragma once
#ifndef _HAFFU_H_
#define _HAFFU_H_
#define HAFFU typedef
HAFFU char TYPE_CHAR; // 哈夫曼树结点的值域之一为 char 类型 表示出现的字符
HAFFU int TYPE_WIGHT; // 哈夫曼树结点的值域之一为 int 类型 表示出现的字符的权重
HAFFU int NODE_NUMBER; // 哈夫曼树的结点总数
#include <stack>
template <class T>
using Stack = std::stack<T>;
HAFFU struct haffu_c{
/*数据部分*/
TYPE_CHAR elem; // 出现的成员
TYPE_WIGHT wight; // 权重
struct haffu_c* lchild, * rchild; // 左孩子 和 右孩子
/*连接部分*/
struct haffu_c* next; // 下一个结点的地址 这里类似于共享单链表 承载着数的结点
}haffuNode, *haffuNodeP;
// 先序遍历
void
preOrder(haffuNodeP haffu_tree);
// 中序
void
cenOrder(haffuNodeP haffu_tree);
// 得到哈夫曼树的 所有结点数量
NODE_NUMBER
getHaffuNodeNumber(haffuNodeP haffu_tree);
// 得到哈夫曼树的所有叶子结点 返回的是所有的叶子结点的数组
TYPE_CHAR*
getHaffuLeaf(haffuNodeP haffu_tree, int maxlen);
// 求哈夫曼编码 返回的是该叶子结点的哈夫曼编码的数组 0 1(二进制) 形式
void
getHaffuCoding(haffuNodeP haffu_tree, TYPE_CHAR leaf, TYPE_CHAR*, int& index);
// 树的销毁
void
destroyTree(haffuNodeP &haffu_tree);
#endif // !_HAFFU_H_
#include <iostream>
#include "haffu_tree.h"
#include <string.h>
void
preOrder(haffuNodeP haffu_tree)
{
if (!haffu_tree) return;
printf_s("--%c[%d]--", haffu_tree->elem, haffu_tree->wight);
preOrder(haffu_tree->lchild);
preOrder(haffu_tree->rchild);
return;
}
void
cenOrder(haffuNodeP haffu_tree)
{
if (!haffu_tree) return;
preOrder(haffu_tree->lchild);
printf_s("--%c[%d]--", haffu_tree->elem, haffu_tree->wight);
preOrder(haffu_tree->rchild);
return;
}
void
destroyTree(haffuNodeP &haffu_tree)
{
if (!haffu_tree)return;
haffuNodeP tmp[100];
int in = 0;
int out = 0;
tmp[in++] = haffu_tree;
while (in > out) {
if (tmp[out]) {
tmp[in++] = tmp[out]->lchild;
tmp[in++] = tmp[out]->rchild;
}
out++;
}
for (int i = out - 1; i > -1; i--) {
if (tmp[i]) delete tmp[i];
}
return;
}
NODE_NUMBER
getHaffuNodeNumber(haffuNodeP haffu_tree)
{
if (!haffu_tree)return 0;
return getHaffuNodeNumber(haffu_tree->lchild)
+ getHaffuNodeNumber(haffu_tree->rchild) + 1;
}
TYPE_CHAR*
getHaffuLeaf(haffuNodeP haffu_tree, int maxlen)
{
if (!haffu_tree) return nullptr; // 这是个空树
// 最大一百个 叶子结点 其实 可以 根据结点总数算出来
TYPE_CHAR* leaf = (TYPE_CHAR*)calloc(maxlen, sizeof(TYPE_CHAR));
if (!leaf) return nullptr;
haffuNodeP tmp = haffu_tree; // 用于遍历的结点
int count = 0; // 记录叶子结点的下标
Stack<haffuNodeP> stack;
stack.push(haffu_tree);
while (!stack.empty()) {
tmp = stack.top(); // 得到栈定元素
if (!tmp->lchild && !tmp->rchild) {
leaf[count++] = tmp->elem;
}
stack.pop();
if (tmp->rchild)stack.push(tmp->rchild);
if (tmp->lchild)stack.push(tmp->lchild);
}
return leaf;
}
#include <iostream>
#include <time.h>
#include <Windows.h>
#include "priority_queue.h"
#include <cstdlib> //*
#include <crtdbg.h> //*
#ifdef _DEBUG //*
#ifndef DBG_NEW //*
#define DBG_NEW new (_NORMAL_BLOCK, __FILE__, __LINE__)//*
#define new DBG_NEW //*
#endif //*
#endif
using namespace std;
int main(void)
{
clock_t start, end;
start = clock();
priority_queueP PQ = nullptr;
// 初始化
if (initPriorityQueue(PQ)) {
if (DeBug)printf_s("队列初始化成功!\n");
}
else {
if (DeBug)printf_s("队列初始化失败!\n");
exit(-1);
}
srand((unsigned)time(nullptr));
// 插入
if (DeBug)cout << "******************入队********************" << endl;
ELEM_TYPE* node;
for (int i = 0; i < 10; i++) {
node = new ELEM_TYPE;
node->elem = i + 'a';
node->wight = 5 - i;
node->next = nullptr;
node->lchild = nullptr;
node->rchild = nullptr;
if (insertQueue(PQ, node)) {
if (DeBug)printf_s("插入成功! \n");
}
else {
if (DeBug)printf_s("插入失败!\n");
if (node) delete node;
}
}
if (DeBug) printQueue(PQ);
cout << endl;
// 优先队列的出队
if (DeBug)cout << "******************出队********************" << endl;
ELEM_TYPE* out_node = nullptr;
for (int i = 0; i < 3; i++) {
if (out_node = popQueue(PQ)){
if (DeBug)printf_s("出队元素%c[%d] \n", out_node->elem, out_node->wight);
if (out_node)delete out_node;
}
else {
if (DeBug)printf_s("出队失败!\n");
}
}
// 遍历
if (DeBug) printQueue(PQ);
cout << endl;
// 构建哈夫曼树
haffuNodeP haffu_tree = nullptr;
buildHaffu(PQ, haffu_tree);
// 先序遍历
if (DeBug) cout << "哈夫曼树的先序遍历:" << endl;
preOrder(haffu_tree);
cout << endl;
// 中序遍历
if (DeBug) cout << "哈夫曼树的中序遍历:" << endl;
cenOrder(haffu_tree);
cout << endl;
// 得到树的结点总数
int maxlen = getHaffuNodeNumber(haffu_tree);
if (DeBug) cout << "哈夫曼树的结点总数:" << maxlen << endl;
// 得到树的叶子数组
if (DeBug) cout << "哈夫曼树的叶子结点总数:" << endl;
TYPE_CHAR* leaf_str = getHaffuLeaf(haffu_tree, maxlen);
int reallenth = strlen(leaf_str);
for (int i = 0; i < reallenth; i++) {
cout << leaf_str[i] << " ";
}
cout << endl;
delete[] leaf_str;
destroyTree(haffu_tree);
destroyQueue(PQ);
if (DeBug) cout << "哈夫曼树 和 队列 销毁成功!" << endl;
end = clock();
cout << start << " ";
cout << end << endl;
printf("总共用了 %d 个系统时间 \n", int(end - start));
system("pause");
_CrtDumpMemoryLeaks();
return 0;
}