本例程实现二叉树的二叉链表存储结构类的定义、实现、应用以及Huffman树,包括:
三种构造函数:
1、键盘输入扩展二叉树的前序序列构造二叉树
2、由扩展二叉树的前序遍历序列s构造二叉树
3、由扩展二叉树的前序遍历序列sp,中序遍历序列sm构造二叉树
析构函数:释放二叉链表中各结点的存储空间
获得指向根结点的指针
二叉树的遍历:
1、前中后序遍历二叉树的递归实现
2、前中后序遍历二叉树的非递归实现,后序遍历二叉树只进一次栈的非递归实现
3、层序遍历二叉树
应用:
1、求二叉树结点个数
2、前序遍历顺序输出二叉树叶子结点
3、非递归中序遍历顺序输出二叉树叶子结点
4、求二叉树的高度
5、计算二叉树中有所有叶子结点的和
6、Huffman树
#include
#include
#include
using namespace std;
int m=0;
template
struct BiNode //二叉树的结点结构
{
T data;
BiNode
};
template
struct BiNodeTag //用于后序遍历二叉树非递归实现(2次进栈)的结点结构
{
char tag;
BiNode
};
template
class BiTree
{ //二叉树类
public:
BiTree( ); //构造函数,键盘输入扩展二叉树的前序序列构造二叉树
BiTree(char *s); //构造函数,由扩展二叉树的前序遍历序列s构造二叉树
BiTree(string sp,string sm); //构造函数,由扩展二叉树的前序遍历序列sp,中序遍历序列sm构造二叉树
~BiTree(void); //析构函数,释放二叉链表中各结点的存储空间
BiNode
void PreOrder(BiNode
void PreOrder0(BiNode
void InOrder(BiNode
void InOrder0(BiNode
void PostOrder(BiNode
void PostOrder0(BiNode
void PostOrder1(BiNode
void LevelOrder(BiNode
private:
BiNode
BiNode
BiNode
BiNode
void Release(BiNode
};
/*
*前置条件:二叉树不存在
*输 入:无
*功 能:构造一棵二叉树
*输 出:无
*后置条件:产生一棵二叉树
*/
template
BiTree
{
m=0;
root = Creat(s);
}
template
BiTree
{
root = Creat();
}
template
BiTree
{
root = Creat(sp,sm);
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:释放二叉链表中各结点的存储空间
*输 出:无
*后置条件:二叉树不存在
*/
template
BiTree
{
Release(root);
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:获取指向二叉树根结点的指针
*输 出:指向二叉树根结点的指针
*后置条件:二叉树不变
*/
template
BiNode
{
return root;
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:前序遍历二叉树
*输 出:二叉树中结点的一个线性排列
*后置条件:二叉树不变
*/
template
void BiTree
{
if(root==NULL) return;
else{
cout<
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:中序遍历二叉树
*输 出:二叉树中结点的一个线性排列
*后置条件:二叉树不变
*/
template
void BiTree
{
if (root==NULL) return; //递归调用的结束条件
else{
InOrder(root->lchild); //中序递归遍历root的左子树
cout<
InOrder(root->rchild); //中序递归遍历root的右子树
}
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:后序遍历二叉树
*输 出:二叉树中结点的一个线性排列
*后置条件:二叉树不变
*/
template
void BiTree
{
if (root==NULL) return; //递归调用的结束条件
else{
PostOrder(root->lchild); //后序递归遍历root的左子树
PostOrder(root->rchild); //后序递归遍历root的右子树
cout<
}
}
/*
*前置条件:二叉树已存在
*输 入:无
*功 能:层序遍历二叉树
*输 出:二叉树中结点的一个线性排列
*后置条件:二叉树不变
*/
template
void BiTree
{
const int MaxSize = 100;
int front = 0;
int rear = 0; //采用顺序队列,并假定不会发生上溢
BiNode
BiNode
if (root==NULL) return;
else{
Q[rear++] = root;
while (front != rear)
{
q = Q[front++];
cout<
if (q->lchild != NULL) Q[rear++] = q->lchild;
if (q->rchild != NULL) Q[rear++] = q->rchild;
}
}
}
/*
*前置条件:空二叉树
*输 入:数据ch;
*功 能:初始化一棵二叉树,构造函数调用
*输 出:无
*后置条件:产生一棵二叉树
*/
//int m=0;
template
BiNode
{
BiNode
char ch=s[m++];
//cout<<"请输入创建一棵二叉树的结点数据"<
if (ch=='#') root = NULL;
else{
root = new BiNode
root->data=ch;
root->lchild = Creat(s ); //递归建立左子树
root->rchild = Creat(s ); //递归建立右子树
}
return root;
}
template
BiNode
{
BiNode
if(sp.length() > 0)
{
root=new BiNode
root->data=sp[0];
int index=sm.find(sp[0]);
string in_left_str=sm.substr(0, index);
string in_right_str=sm.substr(index+1);
string pre_left_str=sp.substr(1, index);
string pre_right_str=sp.substr(index+1);
root->lchild = Creat(pre_left_str, in_left_str); //递归建立左子树
root->rchild = Creat(pre_right_str, in_right_str); //递归建立右子树
}
return root;
}
template
BiNode
{ BiNode
char ch;
cout<<"Input a char: ";
cin>>ch;
if (ch=='#') root=NULL;
else {
root=new BiNode
root->data=ch;
root-> lchild=Creat();
root-> rchild=Creat();
}
return root;
}
/*
*前置条件:二叉树已经存在
*输 入:无
*功 能:释放二叉树的存储空间,析构函数调用
*输 出:无
*后置条件:二叉树不存在
*/
template
void BiTree
{
if (root != NULL){
Release(root->lchild); //释放左子树
Release(root->rchild); //释放右子树
delete root;
}
}
template
void BiTree
{//前序遍历二叉树非递归
const int MaxStackSize=100;
BiNode
int top= -1; // 构造空栈,采用顺序栈,并假定不会发生上溢
while (root!=NULL||top!= -1)
{
while (root!= NULL)
{
cout<
S[++top]=root;;
root=root->lchild;
}
if (top!= -1) {
root=S[top--];
root=root->rchild;
}
}
}
template
void BiTree
{//中序遍历二叉树非递归
const int MaxStackSize=100;
BiNode
int top= -1; // 构造空栈,采用顺序栈,并假定不会发生上溢
while (root!=NULL||top!= -1)
{
while (root!= NULL)
{
S[++top]=root;
root=root->lchild;
}
if (top!= -1) {
root=S[top--];cout<
root=root->rchild;
}
}
}
template
void BiTree
{//二叉树后序遍历非递归 2次入栈
const int MaxStackSize=100;
BiNodeTag
BiNodeTag
int top= -1; // 构造空栈,采用顺序栈,并假定不会发生上溢
while (root!=NULL||top!= -1)
{
while (root!= NULL)
{
p.pt=root;p.tag='L';
S[++top]=p;
root=root->lchild;
}
if (top!= -1) {
p=S[top--];
if(p.tag=='L'){p.tag='R';S[++top]=p;root=p.pt->rchild;}
else if(p.tag=='R'){cout<
}
}
}
}
template
void BiTree
{
//二叉树后序遍历非递归 一次入栈:
//后序遍历在中序的双层循环的基础上需要加入一个记录记录上一次出栈的节点。步骤如下:
//1、如果栈顶元素非空且左孩子存在,将左孩子入栈,重复该过程。若不存在则进入第2步(该过程和中序遍历一致)
//2、判断上一次出栈节点是否当前节点的右孩子,或者当前节点是否存在右孩子,满足任一条件,将当前节点输出,并出栈。否则将右节点压栈。跳至第1步
const int MaxStackSize=100;
BiNode
int top= -1; // 构造空栈,采用顺序栈,并假定不会发生上溢
if(root == NULL) return;
S[++top]=root;
BiNode
while(top!= -1)
{
while(S[top]->lchild != NULL)
{
top++;
S[top]=S[top-1]->lchild;
}
while(top!= -1)
{
if(lastpop == S[top]->rchild || S[top]->rchild == NULL)
{//判断上次弹出的结点是不是当前结点的右孩子,或者当前节点没有右孩子,因为访问次序是“左-右-中”。
cout<data;
lastpop = S[top--];
}
else if(S[top]->rchild != NULL)
{
top++;
S[top]=S[top-1]->rchild;
break;
}
}
}
}
template
void Count(BiNode
{//求二叉树结点个数
if (root) {
Count(root->lchild,n);
n++;
Count(root->rchild,n);
}
}
template
int CountNodes(BiNode
int n=0;
Count(root,n);
return n;
}
template
int num_of_nodes(BiNode
{
if(t == NULL)return 0;
int nl=num_of_nodes(t->lchild);
int nr=num_of_nodes(t->rchild);
return 1+nl+nr;
}
template
void PreOrderleaf(BiNode
{
if (root) {
if (!root->lchild && !root->rchild)
cout<
PreOrderleaf(root->lchild);
PreOrderleaf(root->rchild);
}
}
template
void InOrder0leaf(BiNode
{ //非递归中序遍历顺序输出二叉树叶子结点
const int MaxStackSize=100;
BiNode
int top= -1; // 构造空栈,采用顺序栈,并假定不会发生上溢
while (root!=NULL||top!= -1)
{
while (root!= NULL)
{
S[++top]=root;;
root=root->lchild;
}
if (top!= -1) {
root=S[top--];
if(!root->rchild && !root->lchild) cout<
root=root->rchild;
}
}
}
template
int Depth(BiNode
{//求二叉树的高度
if (root==NULL) return 0;
else {
int hl=Depth(root->lchild);
int hr=Depth(root ->rchild);
return hl>hr?hl+1:hr+1;
}
}
template
int CountDC(BiNode
//计算二叉树中有所有叶子结点的和。
{
if (root==NULL) return 0;
else{
if (root->lchild==NULL&& root->rchild==NULL)
return (int)(root->data);
else
return (CountDC(root->lchild)+CountDC(root->rchild));
}
}
// 哈夫曼树的结点结构
struct element
{
int weight; // 权值域
int lchild, rchild, parent; // 该结点的左、右、双亲结点在数组中的下标
};
// 选取权值最小的两个结点
void selectMin(element a[],int n, int &s1, int &s2)
{
for (int i = 0; i < n; i++)
{
if (a[i].parent == -1)// 初始化s1,s1的双亲为-1
{
s1 = i;
break;
}
}
for (int i = 0; i < n; i++)// s1为权值最小的下标
{
if (a[i].parent == -1 && a[s1].weight > a[i].weight)
s1 = i;
}
for (int j = 0; j < n; j++)
{
if (a[j].parent == -1&&j!=s1)// 初始化s2,s2的双亲为-1
{
s2 = j;
break;
}
}
for (int j = 0; j < n; j++)// s2为另一个权值最小的结点
{
if (a[j].parent == -1 && a[s2].weight > a[j].weight&&j != s1)
s2 = j;
}
}
// 哈夫曼算法
// n个叶子结点的权值保存在数组w中
void HuffmanTree(element huftree[], int w[], int n)
{
for (int i = 0; i < 2*n-1; i++) // 初始化,所有结点均没有双亲和孩子
{
huftree[i].parent = -1;
huftree[i].lchild = -1;
huftree[i].rchild = -1;
}
for (int i = 0; i < n; i++) // 构造只有根节点的n棵二叉树
{
huftree[i].weight = w[i];
}
for (int k = n; k < 2 * n - 1; k++) // n-1次合并
{
int i1, i2;
selectMin(huftree, k, i1, i2); // 查找权值最小的俩个根节点,下标为i1,i2
// 将i1,i2合并,且i1和i2的双亲为k
huftree[i1].parent = k;
huftree[i2].parent = k;
huftree[k].lchild = i1;
huftree[k].rchild = i2;
huftree[k].weight = huftree[i1].weight + huftree[i2].weight;
}
}
// 输出哈夫曼树
void print(element hT[],int n)
{
cout << "index weight parent lChild rChild" << endl;
cout << left; // 左对齐输出
for (int i = 0; i < n; ++i)
{
cout << setw(5) << i << " ";
cout << setw(6) << hT[i].weight << " ";
cout << setw(6) << hT[i].parent << " ";
cout << setw(6) << hT[i].lchild << " ";
cout << setw(6) << hT[i].rchild << endl;
}
}
int main() BiTree cout<<"------前序遍历------ "< // BiTree return 0;
{ BiNode
BiTree
root = bt.Getroot( ); //获取指向根结点的指针
cout<<"------前序遍历------ "<
cout<
cout<
cout<
cout<
cout<
cout<
cout<
PreOrderleaf(root);
cout<
cout<
//BiNode
root = bt1.Getroot( );
cout<
cout<
cout<
cout<
cout<
cout<
cout<
Count(root);
cout<<"Number of nodes="<
PreOrderleaf(root);
cout<
cout<
BiTree
root = bt2.Getroot( ); //获取指向根结点的指针
cout<<"------前序遍历------ "<
int x[] = { 5,29,7,8,14,23,3,11 }; // 权值集合
element *hufftree=new element[2*8-1]; // 动态创建数组
HuffmanTree(hufftree, x, 8);
print(hufftree,15);
}