图形化二叉树及构造字符串的哈夫曼树并图形化展示
设计说明
采用EasyX绘图,采用扩展二叉树的前序序列还原二叉树
# include <graphics.h>
# include <stdlib.h>
# include <math.h>
# include <iostream>
using namespace std;
#define RATE 10
#define BASE_WIDTH 80
#define BASE_HEIGHT 60
#define WIDTH 800
#define HEIGHT 600
typedef char elementType;
struct Node
{
elementType data;
Node* left;
Node* right;
};
Node* createTreeByExtendStr(string extendStr, int& startIndex);
int getHeight(Node* root);
void draw(Node* root, int x, int y, double height);
void draw(Node* root);
int main()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(WHITE);
setlinecolor(RED);
setcolor(RED);
cleardevice();
//string extendStr = "AB.D..CE...";
string extendStr = "ABC.I.J.K..D..EF.H..G.";
int startIndex = 0;
Node* root = createTreeByExtendStr(extendStr, startIndex);
draw(root);
system("pause");
return 0;
}
Node* createTreeByExtendStr(string extendStr, int& startIndex)
{
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL)
{
cout << "内存不足,空间分配出错" << endl;
return NULL;
}
if (startIndex == extendStr.length() || extendStr[startIndex] == '.')
{
node = NULL;
return node;
}
node->data = extendStr[startIndex];
startIndex += 1;
Node* left = createTreeByExtendStr(extendStr, startIndex);
startIndex += 1;
Node* right = createTreeByExtendStr(extendStr, startIndex);
node->left = left;
node->right = right;
return node;
}
int getHeight(Node* root)
{
if (root == NULL)
{
return 0;
}
return max(getHeight(root->left), getHeight(root->right)) + 1;
}
void draw(Node* root, int x, int y, double height)
{
if (root == NULL)
{
return;
}
outtextxy(x, y, root->data);
if (root->left != NULL)
{
line(x, y + 15, x - BASE_WIDTH * height / 2, y + BASE_HEIGHT);
}
if (root->right != NULL)
{
line(x, y + 15, x + BASE_WIDTH * height / 2, y + BASE_HEIGHT);
}
draw(root->left, x - BASE_WIDTH * height / 2, y + BASE_HEIGHT, height / 2);
draw(root->right, x + BASE_WIDTH * height / 2, y + BASE_HEIGHT, height / 2);
}
void draw(Node* root)
{
int height= getHeight(root);
setorigin(WIDTH / 2, HEIGHT / 2 - height * BASE_HEIGHT / 2);
draw(root, 0, 0, height);
}
测试效果(还可以再进行调整,修改为采用类来写更合适一些,且可以考虑添加上宽度和高度设置)
字符串的哈夫曼树构造
构造思路:
构造哈夫曼树的思路大致分为三步:
(1)得到各字符出现的频率
(2)将出现的频率转化为列表并排序,每次选取最小的权值组成一颗新的二叉树,将新的二叉树加入到列表中,将原来的两颗二叉树删除;重复这个过程,直到只剩下最后一棵二叉树,即为根节点
(3)输出二叉树的路径,按照左边为0,右边为1,直到叶子节点才表示一个编码
# include <iostream>
# include <stdlib.h>
# include <algorithm>
# include <vector>
# include <map>
using namespace std;
// 由字符串转化成哈夫曼编码得到哈夫曼树
typedef int elementType;
struct Node
{
char data;
int value;
Node* left;
Node* right;
};
// 将字符串转化为二元组形式,表示各个字符出现的频率
map<char, int> getList(string text);
// 通过二元组创建哈夫曼树
Node* createHafumanTree(vector<Node*> list);
//自定义排序函数
bool cmp(const Node* node1, const Node* node2)
{
return node1->value > node2->value;
}
void getCodes(Node* root, string path);
int main()
{
string text = "abcdefgabcdefgabcd123";
map<char, int> map = getList(text);
vector<Node*> list;
for (auto& it : map)
{
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL)
{
cout << "内存不足" << endl;
return 0;
}
node->data = it.first;
node->value = it.second;
node->left = NULL;
node->right = NULL;
list.push_back(node);
}
for (auto& it : list)
{
cout << it->data << " " << it->value << endl;
}
Node* root = createHafumanTree(list);
getCodes(root, "");
system("pause");
}
map<char, int> getList(string text)
{
map<char, int> map;
for (int i = 0; i < text.length(); i++)
{
if (map.count(text[i]) == 1)
{
map[text[i]] = map[text[i]] + 1;
}
else
{
map[text[i]] = 1;
}
}
return map;
}
Node* createHafumanTree(vector<Node*> list)
{
while (list.size() > 1)
{
sort(list.begin(), list.end(), cmp);
Node* left = list.at(list.size() - 1);
Node* right = list.at(list.size() - 2);
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL)
{
cout << "内存不足" << endl;
return NULL;
}
node->value = left->value + right->value;
node->left = left;
node->right = right;
list.pop_back();
list.pop_back();
list.push_back(node);
}
return list.at(0);
}
void getCodes(Node* root, string path)
{
if (root == NULL)
{
return;
}
if (root->left == NULL && root->right == NULL)
{
cout << root->data << " " << path << endl;
}
getCodes(root->left, path + "0");
getCodes(root->right, path + "1");
}
演示结果:
图形化展示
# include <graphics.h>
# include <stdlib.h>
# include <math.h>
# include <iostream>
# include <algorithm>
# include <vector>
# include <map>
using namespace std;
// 由字符串转化成哈夫曼编码得到哈夫曼树
#define RATE 10
#define BASE_WIDTH 80
#define BASE_HEIGHT 60
#define WIDTH 1200
#define HEIGHT 600
typedef char elementType;
struct Node
{
char data;
int value;
Node* left;
Node* right;
};
int getHeight(Node* root);
void draw(Node* root, int x, int y, double height);
void draw(Node* root);
// 将字符串转化为二元组形式,表示各个字符出现的频率
map<char, int> getList(string text);
// 通过二元组创建哈夫曼树
Node* createHafumanTree(vector<Node*> list);
//自定义排序函数
bool cmp(const Node* node1, const Node* node2)
{
return node1->value > node2->value;
}
int main()
{
initgraph(WIDTH, HEIGHT);
setbkcolor(WHITE);
setlinecolor(RED);
setcolor(RED);
cleardevice();
string text = "abcdefgabcdefgabcd123";
map<char, int> map = getList(text);
vector<Node*> list;
for (auto& it : map)
{
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL)
{
cout << "内存不足" << endl;
return 0;
}
node->data = it.first;
node->value = it.second;
node->left = NULL;
node->right = NULL;
list.push_back(node);
}
for (auto& it : list)
{
cout << it->data << " " << it->value << endl;
}
Node* root = createHafumanTree(list);
draw(root);
system("pause");
return 0;
}
int getHeight(Node* root)
{
if (root == NULL)
{
return 0;
}
return max(getHeight(root->left), getHeight(root->right)) + 1;
}
void draw(Node* root, int x, int y, double height)
{
if (root == NULL)
{
return;
}
outtextxy(x, y, root->data);
if (root->left != NULL)
{
line(x, y + 15, x - BASE_WIDTH * height / 2, y + BASE_HEIGHT);
}
if (root->right != NULL)
{
line(x, y + 15, x + BASE_WIDTH * height / 2, y + BASE_HEIGHT);
}
draw(root->left, x - BASE_WIDTH * height / 2, y + BASE_HEIGHT, height / 2);
draw(root->right, x + BASE_WIDTH * height / 2, y + BASE_HEIGHT, height / 2);
}
void draw(Node* root)
{
int height = getHeight(root);
setorigin(WIDTH / 2, HEIGHT / 2 - height * BASE_HEIGHT / 2);
draw(root, 0, 0, height);
}
map<char, int> getList(string text)
{
map<char, int> map;
for (int i = 0; i < text.length(); i++)
{
if (map.count(text[i]) == 1)
{
map[text[i]] = map[text[i]] + 1;
}
else
{
map[text[i]] = 1;
}
}
return map;
}
Node* createHafumanTree(vector<Node*> list)
{
while (list.size() > 1)
{
sort(list.begin(), list.end(), cmp);
Node* left = list.at(list.size() - 1);
Node* right = list.at(list.size() - 2);
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL)
{
cout << "内存不足" << endl;
return NULL;
}
node->value = left->value + right->value;
node->data = 32;
node->left = left;
node->right = right;
list.pop_back();
list.pop_back();
list.push_back(node);
}
return list.at(0);
}
展示效果