图形化二叉树(只能用VS运行)及构造字符串的哈夫曼树并图形化展示

图形化二叉树及构造字符串的哈夫曼树并图形化展示

设计说明

采用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);
}

展示效果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值