目录
内容描述
1. 普通二叉树和线索二叉树
实现树的节点 TreeNode(支持线索二叉树)和树 MyTree(支持线索二叉树),采用二叉链表存储,完成以下功能:
- 树节点的初始化和销毁
- 树初始化,初始化一棵空树
- 树初始化,根据二叉树的先序序列,生成二叉树的二叉链表存储,使用 @ 表示 NULL
- 树的复制构造函数,复制参数中的树
- 树销毁,支持普通二叉树与线索二叉树
- 先序遍历二叉树并打印,仅支持普通二叉树,不考虑线索化,对节点的访问操作为打印该节点
- 中序遍历二叉树并打印,支持普通二叉树与线索二叉树,对节点的访问操作为打印该节点
- 后序遍历二叉树并打印,仅支持普通二叉树,不考虑线索化,对节点的访问操作为打印该节点
- 定位二叉树中的节点,在树中找到值为v的节点则返回该节点,否则返回 NULL,支持普通二叉树与线索二叉树
- 计算二叉树的叶子结点数,仅支持普通二叉树,不考虑线索化
- 计算二叉树的深度,仅支持普通二叉树,不考虑线索化
- 当前树是否是线索二叉树,是线索二叉树返回 true,否则 false
- 为二叉树生成中序线索二叉树
- 寻找中序线索二叉树中某节点的前驱节点,仅支持线索二叉树
- 寻找中序线索二叉树中某节点的后继节点,仅支持线索二叉树
2. 霍夫曼树
实现霍夫曼树 HuffmanTree,输出对应的霍夫曼编码,具体完成以下功能:
- 树初始化 HuffmanTree,根据输入创建一棵霍夫曼树,第一个参数为节点个数,第二个参数为节点数组,节点值为节点重要度,越大代表越重要,要求树构建时偏小的值放入左子树,偏大的值放入右子树
- 树销毁
- 输出霍夫曼编码,格式:节点值:编码,节点排序递减
- 其他必要的函数
3. 输入输出示例
MyTree myTree("ABC@@DE@G@@F@@@");
myTree.preOrderTraverse();//ABCDEGF
cout << endl;
myTree.inOrderTraverse();//CBEGDFA
cout << endl;
myTree.postOrderTraverse();//CGEFDBA
cout << endl;
cout << myTree.countLeaf() << endl;//3
cout << myTree.countHeight() << endl;//5
MyTree myThreadedTree(myTree);
cout << myThreadedTree.isThreadedTree() << endl;//0
myThreadedTree.inOrderThreading();
cout << myThreadedTree.isThreadedTree() << endl;//1
myThreadedTree.inOrderTraverse();//CBEGDFA
cout << endl;
TreeNode n = myThreadedTree.locateNode('G');
myThreadedTree.preNode(n).printNode();//E
cout << endl;
myThreadedTree.nextNode(n).printNode();//D
cout << endl; int v[] = {2,7,5,4};
HuffmanTree hTree(4, v);
hTree.printHuffmanCodes();
/*
7:0
5:10
4:111
2:110
*/
程序代码
TreeNode.h
#ifndef TREENODE_H
#define TREENODE_H
class TreeNode
{
public:
char data;
TreeNode* lchild, * rchild;
bool ltag, rtag;
TreeNode();
~TreeNode();
void printNode();
};
#endif
MyTree.h
#ifndef MyTree_H
#define MyTree_H
#include "TreeNode.h"
class MyTree {
private:
TreeNode* treeNode;
void preOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn));
void inOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn));
void postOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn));
void createTree(TreeNode*& tn, const char*& str);
void createTree(TreeNode*& tn, const TreeNode* tn0);
int Leaf(TreeNode*&& tn);
int Height(TreeNode*&& tn);
bool isThr(TreeNode*&& tn);
void inOrderThr(TreeNode*& tn, TreeNode*&& pre);
bool locate(char c, TreeNode* tn, TreeNode*& temp);
public:
MyTree();
MyTree(const char* str);
MyTree(MyTree& mt);
~MyTree();
void preOrderTraverse();
void inOrderTraverse();
void postOrderTraverse();
int countLeaf();
int countHeight();
bool isThreadedTree();
void inOrderThreading();
TreeNode locateNode(char c);
TreeNode preNode(TreeNode tn);
TreeNode nextNode(TreeNode tn);
};
#endif
Huffman.h
#ifndef HUFFMANTREE_H
#define HUFFMANTREE_H
class HuffmanTree {
private:
typedef struct
{
int weight; //结点的权值,为了方便直接用int
int parent, lChild, rChild; //左右孩子和双亲
}HTNode,*HTree;
HTree htree;
int n;
void select(int n, int& s1, int& s2);
public:
HuffmanTree(int n, int w[]);
~HuffmanTree();
void printHuffmanCodes();
};
#endif
TreeNode.cpp
#include "TreeNode.h"
#include<bits/stdc++.h>
TreeNode::TreeNode()
{
data = 0;
lchild = nullptr;
rchild = nullptr;
ltag = 0;
rtag = 0;
}
void TreeNode::printNode() {
std::cout << data;
}
TreeNode::~TreeNode() {}
MyTree.cpp
#include "MyTree.h"
#include <bits/stdc++.h>
MyTree::MyTree() {
treeNode = nullptr;
}
MyTree::MyTree(const char* str) {
createTree(treeNode, str);
}
MyTree::MyTree(MyTree& mt) {
createTree(treeNode, mt.treeNode);
if (mt.isThreadedTree())
inOrderThreading();
}
MyTree::~MyTree() {
postOrder(treeNode, [](TreeNode*& tn)->void {delete tn; });
}
void MyTree::createTree(TreeNode*& tn, const char*& str)
{
if (*str)
{
if (*str == '@')
{
tn = nullptr;
return;
}
tn = new TreeNode;
tn->data = *str;
createTree(tn->lchild, ++str);
createTree(tn->rchild, ++str);
}
}
void MyTree::createTree(TreeNode*& tn, const TreeNode* tn0)
{
if (tn0 == nullptr)
{
tn = nullptr;
return;
}
tn = new TreeNode;
tn->data = tn0->data;
createTree(tn->lchild, tn0->lchild);
createTree(tn->rchild, tn0->rchild);
}
void MyTree::preOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn)) {
if (tn == nullptr)return;
(*pf)(tn);
if (tn->ltag == 0)
preOrder(tn->lchild, pf);
if (tn->rtag == 0)
preOrder(tn->rchild, pf);
}
void MyTree::inOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn)) {
if (tn == nullptr)return;
if (tn->ltag == 0)
inOrder(tn->lchild, pf);
(*pf)(tn);
if (tn->rtag == 0)
inOrder(tn->rchild, pf);
}
void MyTree::postOrder(TreeNode*& tn, void(*pf)(TreeNode*& tn)) {
if (tn == nullptr)return;
if (tn->ltag == 0)
postOrder(tn->lchild, pf);
if (tn->rtag == 0)
postOrder(tn->rchild, pf);
(*pf)(tn);
}
void MyTree::preOrderTraverse() {
preOrder(treeNode, [](TreeNode*& tn)->void {std::cout << tn->data; });
}
void MyTree::inOrderTraverse() {
inOrder(treeNode, [](TreeNode*& tn)->void {std::cout << tn->data; });
}
void MyTree::postOrderTraverse() {
postOrder(treeNode, [](TreeNode*& tn)->void {std::cout << tn->data; });
}
int MyTree::countLeaf() {
return Leaf(std::move(treeNode));
}
int MyTree::Leaf(TreeNode*&& tn)
{
if (tn == nullptr)return 0;
else if ((tn->lchild == nullptr && tn->rchild == nullptr) || (tn->ltag == 1 && tn->rtag == 1))
return 1;
else if (tn->rchild == nullptr || tn->rtag == 1)return Leaf(std::move(tn->lchild));
else if (tn->lchild == nullptr || tn->ltag == 1)return Leaf(std::move(tn->rchild));
else return Leaf(std::move(tn->lchild)) + Leaf(std::move(tn->rchild));
}
int MyTree::countHeight() {
return Height(std::move(treeNode));
}
int MyTree::Height(TreeNode*&& tn)
{
if (tn == nullptr)return 0;
else if ((tn->lchild == nullptr && tn->rchild == nullptr) || (tn->ltag == 1 && tn->rtag == 1))
return 1;
else if (tn->rchild == nullptr || tn->rtag == 1)return 1 + Height(std::move(tn->lchild));
else if (tn->lchild == nullptr || tn->ltag == 1)return 1 + Height(std::move(tn->rchild));
else return 1 + std::max(Height(std::move(tn->lchild)), Height(std::move(tn->rchild)));
}
bool MyTree::isThreadedTree() {
return isThr(std::move(treeNode));
}
bool MyTree::isThr(TreeNode*&& tn) {
if (tn == nullptr || (tn->lchild == nullptr && tn->ltag == 0))
return false;
else if (tn->ltag == 1)return true;
else return isThr(std::move(tn->lchild));
}
void MyTree::inOrderThreading()
{
inOrderThr(treeNode, nullptr);
}
void MyTree::inOrderThr(TreeNode*& tn, TreeNode*&& pre)
{
if (tn == nullptr)return;
inOrderThr(tn->lchild, std::move(pre));
if (tn->lchild == nullptr)
{
tn->lchild = pre;
tn->ltag = 1;
}
if (pre != nullptr && pre->rchild == nullptr)
{
pre->rchild = tn;
pre->rtag = 1;
}
pre = tn;
inOrderThr(tn->rchild, std::move(pre));
}
TreeNode MyTree::locateNode(char c)
{
TreeNode* temp;
locate(c, treeNode, temp);
return *temp;
}
bool MyTree::locate(char c, TreeNode* tn, TreeNode*& temp)
{
if (tn == nullptr)return false;
else if (tn->data == c)
{
temp = tn;
return true;
}
else if ((tn->lchild == nullptr && tn->rchild == nullptr) || (tn->ltag == 1 && tn->rtag == 1))
return false;
else if (tn->rchild == nullptr || tn->rtag == 1)return locate(c, tn->lchild, temp);
else if (tn->lchild == nullptr || tn->ltag == 1)return locate(c, tn->rchild, temp);
else return locate(c, tn->lchild, temp) || locate(c, tn->rchild, temp);
}
TreeNode MyTree::preNode(TreeNode tn) {
if (tn.ltag == 1)return *tn.lchild;
else {
TreeNode* p = tn.lchild;
while (p->rtag == 0)
{
p = p->rchild;
}
return *p;
}
}
TreeNode MyTree::nextNode(TreeNode tn)
{
if (tn.rtag == 1)
return *tn.rchild;
else {
TreeNode* p = tn.rchild;
while (p->ltag == 0)
{
p = p->lchild;
}
return *p;
}
}
Huffman.cpp
#include "Huffman.h"
#include <bits/stdc++.h>
HuffmanTree::HuffmanTree(int n, int w[]) {
int s1;
int s2;
this->n = n;
int m = 2 * n - 1;
htree = new HTNode[m];
//1--n号空间存放叶子结点,初始化结点
for (int i = 0; i < n; i++) {
//其中叶子结点的权值是w[n]数组保存
htree[i].weight = w[i];
htree[i].lChild = -1;
htree[i].rChild = -1;
htree[i].parent = -1;
}
//对于其它的结点即非叶子结点
for (int i = n; i < m; i++) {
htree[i].weight = -1;
htree[i].lChild = -1;
htree[i].rChild = -1;
htree[i].parent = -1;
}
//创建非叶子结点,构建哈夫曼树
for (int i = n; i < m; i++) {
//找到权值最小的两个结点,分别赋值给s1和s2
select(i, s1, s2);
htree[s1].parent = i;
htree[s2].parent = i;
htree[i].lChild = s1;
htree[i].rChild = s2;
htree[i].weight = htree[s1].weight + htree[s2].weight;
}
}
HuffmanTree::~HuffmanTree() {
delete[]htree;
}
void HuffmanTree::select(int num, int& s1, int& s2) {
int min;
//遍历全部的结点,找出一个单结点
for (int i = 0; i < num; i++) {
if (htree[i].parent == -1) {
min = i;
break;
}
}
//继续遍历全部结点,找出权值最小的单结点
for (int i = 0; i < num; i++) {
if (htree[i].parent == -1) {
if (htree[i].weight < htree[min].weight) {
min = i;
}
}
}
s1 = min;
//进行和上面相同的操作,找到第二小的结点
for (int i = 0; i < num; i++) {
if (htree[i].parent == -1 && i != s1) {
min = i;
break;
}
}
for (int i = 0; i < num; i++) {
if (htree[i].parent == -1 && i != s1) {
if (htree[i].weight < htree[min].weight) {
min = i;
}
}
}
s2 = min;
}
void HuffmanTree::printHuffmanCodes() {
//从n个叶子结点到根求哈弗曼编码
std::string* huffmanCode = new std::string[n]; //创建一个储存编码的数组
for (int i = 0; i < n; i++) {
std::string code = "";
//这里我们从叶子结点开始向上遍历
for (int c = i, p = htree[i].parent; p != -1; c = p, p = htree[p].parent) {
if (htree[p].lChild == c) {
code = "0" + code; //如果该结点是双亲结点的左孩子,则在编码前加‘0’
}
else {
code = "1" + code; //如果该结点是双亲结点的右孩子,则在编码前加‘1’
}
}
huffmanCode[i] = code;
}
//节点排序递减输出编码
int* weight = new int[n];
for (int i = 0; i < n; ++i)
{
weight[i] = htree[i].weight;
}
//简单选择排序
for (int i = 0; i < n; i++) {
int max = i;
for (int j = i + 1; j < n; ++j)
{
if (weight[j] > weight[max]) {
max = j;
}
}
std::cout << weight[max] << ": " << huffmanCode[max] << std::endl;
int temp = weight[max];
weight[max] = weight[i];
weight[i] = temp;
std::string code = huffmanCode[max];
huffmanCode[max] = huffmanCode[i];
huffmanCode[i] = code;
}
/*
// for (int i = 0; i < n; i++) {
// std::cout << htree[i].weight << ": " << huffmanCode[i] << std::endl;
// }
*/
delete[]weight;
delete[]huffmanCode;
}
main.cpp
#include <bits/stdc++.h>
#include "TreeNode.h"
#include "MyTree.h"
#include "Huffman.h"
using namespace std;
int main()
{
MyTree myTree("ABC@@DE@G@@F@@@");
myTree.preOrderTraverse();//ABCDEGF
cout << endl;
myTree.inOrderTraverse();//CBEGDFA
cout << endl;
myTree.postOrderTraverse();//CGEFDBA
cout << endl;
cout << myTree.countLeaf() << endl;//3
cout << myTree.countHeight() << endl;//5
MyTree myThreadedTree(myTree);
cout << myThreadedTree.isThreadedTree() << endl;//0
myThreadedTree.inOrderThreading();
cout << myThreadedTree.isThreadedTree() << endl;//1
myThreadedTree.inOrderTraverse();//CBEGDFA
cout << endl;
TreeNode n = myThreadedTree.locateNode('G');
myThreadedTree.preNode(n).printNode();//E
cout << endl;
myThreadedTree.nextNode(n).printNode();//D
cout << endl; int v[] = {2,7,5,4};
HuffmanTree hTree(4, v);
hTree.printHuffmanCodes();
/*
7:0
5:10
4:111
2:110
*/
return 0;
}
测试结果
结果如图所示: