二叉树的操作
实验内容:
采用二叉链表结构建立二叉树;
(2)编程实现二叉树的先序、中序、后序和层序遍历;
(3)编程实现:求二叉树的高度和叶子结点个数;
(4)应用实现:哈夫曼编码。
#include<iostream>
#include<cstdlib>
#include<cmath>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAXSIZE 100
#define OK 1
#define ERROR 0
typedef char TElemType;
typedef int Status;
typedef int SElemType;
typedef int ElemType;
typedef struct BiTNode
{
TElemType data;
struct BiTNode *lchild,*rchild;
} BiTNode,*BiTree; //树的声明
void preOrderTraverse(BiTree T)//先序遍历的递归算法
{
if(T)
{
cout<<T->data<< " → ";
preOrderTraverse(T->lchild);
preOrderTraverse(T->rchild);
}
}
void InOrderTraverse1(BiTree T)//中序遍历的递归算法
{
if(T)
{
InOrderTraverse1(T->lchild);
cout<<T->data<< " → ";
InOrderTraverse1(T->rchild);
}
}
void postOrderTraverse(BiTree T)//后序遍历的递归算法
{
if(T)
{
postOrderTraverse(T->lchild);
postOrderTraverse(T->rchild);
cout<<T->data<< " → ";
}
}
void CreateBiTree(BiTree &T)//先序遍历的顺序建立二叉链表
{
char ch;
cin>>ch;
if(ch=='#') T=NULL;
else
{
T=new BiTNode;
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
int Depth(BiTree T)//计算二叉树的深度
{
int m,n;
if(T==NULL) return 0;
else
{
m=Depth(T->lchild);
n=Depth(T->rchild);
if(m>n)
{
return(m+1);
}
else
{
return (n+1);
}
}
}
int LeafCount(BiTree T)//计算二叉树的叶子结点个数
{
if(T==NULL)return 0;
if((T->rchild==NULL)&&(T->lchild==NULL))return 1;
else
{
return LeafCount(T->rchild)+LeafCount(T->lchild);
}
}
void FloorPrint(BiTree T) //层序遍历
{
BiTree temp[100]; //创建pTreeNode指针类型的指针数组
int in = 0;
int out = 0;
temp[in++] = T; //先保存二叉树根节点
while (in > out)
{
if (temp[out])
{
cout << temp[out]->data << " → ";
temp[in++] = temp[out]->lchild;
temp[in++] = temp[out]->rchild;
}
out++;
}
}
typedef struct
{
int weight; // 权值
int parent, lChild, rChild; // 双亲及左右孩子的下标
} HTNode, *HuffmanTree;
// 哈夫曼编码表的存储表示
typedef struct
{
char** code; // 编码表
int n; // 编码数
} HuffmanCode;
// 选择权值最小的两颗树
void SelectMin(HuffmanTree hT, int n, int &s1, int &s2)
{
s1 = s2 = 0;
int i;
for(i = 1; i < n; ++ i)
{
if(0 == hT[i].parent)
{
if(0 == s1)
{
s1 = i;
}
else
{
s2 = i;
break;
}
}
}
if(hT[s1].weight > hT[s2].weight)
{
int t = s1;
s1 = s2;
s2 = t;
}
for(i += 1; i < n; ++ i)
{
if(0 == hT[i].parent)
{
if(hT[i].weight < hT[s1].weight)
{
s2 = s1;
s1 = i;
}
else if(hT[i].weight < hT[s2].weight)
{
s2 = i;
}
}
}
}
// 构造有n个权值(叶子节点)的哈夫曼树
void CreateHufmanTree(HuffmanTree &hT)
{
int n, m;
string ch;
cout<<"请输入一串字符"<<endl;
cin>>ch;
cout<<"请输入权值的个数"<<endl;
cin >> n;
m = 2*n - 1;
hT = new HTNode[m + 1]; // 0号节点不使用
for(int i = 1; i <= m; ++ i)
{
hT[i].parent = hT[i].lChild = hT[i].rChild = 0;
}
cout<<"请输入相应的权值"<<endl;
for(int i = 1; i <= n; ++ i)
{
cin >> hT[i].weight; // 输入权值
}
hT[0].weight = m; // 用0号节点保存节点数量
/****** 初始化完毕, 创建哈夫曼树 ******/
for(int i = n + 1; i <= m; ++ i)
{
int s1, s2;
SelectMin(hT, i, s1, s2);
hT[s1].parent = hT[s2].parent = i;
hT[i].lChild = s1;
hT[i].rChild = s2; // 作为新节点的孩子
hT[i].weight = hT[s1].weight + hT[s2].weight; // 新节点为左右孩子节点权值之和
}
}
// 构造根据哈夫曼树来哈夫曼编码
void CreateHuffmanCode(HuffmanTree hT, HuffmanCode &hC)
{
hC.n = (hT[0].weight + 1)/2;
hC.code = new char*[hC.n + 1]; // 0位置不使用
char *cd = new char[hC.n]; // 临时存放每个编码
for(int i = 1; i <= hC.n; ++ i)
{
// 每次从叶子节点向上回溯构造编码
int len = 0, child = i, parent = hT[i].parent;
while(parent != 0)
{
if(hT[parent].lChild == child)
{
cd[len ++] = '0';
}
else
{
cd[len ++] = '1';
}
child = parent;
parent = hT[parent].parent;
}
cd[len] = 0;
reverse(cd, cd + len); // 将序列翻转
hC.code[i] = new char[len];
strcpy(hC.code[i], cd);
}
delete[] cd;
}
// 输出哈夫曼表
void PrintHuffmanCode(HuffmanCode &hC)
{
for(int i = 1; i <= hC.n; ++ i)
{
cout << hC.code[i] << endl;
}
}
int main()
{
BiTree T;
int depth;
int count;
cout<<"创建二叉树,输入二叉树中的数据"<<endl;
CreateBiTree(T);
cout<<endl;
cout<<"先序遍历输出二叉树"<<endl;
preOrderTraverse(T);
cout<<endl;
cout<<"中序遍历输出二叉树"<<endl;
InOrderTraverse1(T);
cout<<endl;
cout<<"后序遍历输出二叉树"<<endl;
postOrderTraverse(T);
cout<<endl;
cout<<"输出树的深度"<<endl;
depth=Depth(T);
cout<<depth;
cout<<endl;
cout<<"输出树的叶子结点个数"<<endl;
count=LeafCount(T);
cout<<count;
cout<<endl;
cout<<"层序遍历输出二叉树"<<endl;
FloorPrint(T);
cout<<endl;
HuffmanTree hT;
CreateHufmanTree(hT);
HuffmanCode hC;
CreateHuffmanCode(hT, hC);
PrintHuffmanCode(hC);
return 0;
}