二叉树类的定义、实现以及应用

本例程实现二叉树的二叉链表存储结构类的定义、实现、应用以及Huffman树,包括:

三种构造函数:

1、键盘输入扩展二叉树的前序序列构造二叉树

2、由扩展二叉树的前序遍历序列s构造二叉树

3、由扩展二叉树的前序遍历序列sp,中序遍历序列sm构造二叉树

析构函数:释放二叉链表中各结点的存储空间

获得指向根结点的指针

二叉树的遍历:

1、前中后序遍历二叉树的递归实现

2、前中后序遍历二叉树的非递归实现,后序遍历二叉树只进一次栈的非递归实现

3、层序遍历二叉树

应用:

1、求二叉树结点个数

2、前序遍历顺序输出二叉树叶子结点

3、非递归中序遍历顺序输出二叉树叶子结点

4、求二叉树的高度

5、计算二叉树中有所有叶子结点的和

6、Huffman树

#include<iostream>
#include<iomanip>
#include<string>
using namespace std;
int m=0;
template <class T>
struct BiNode   //二叉树的结点结构
{
  T data;
  BiNode<T> *lchild, *rchild;
};
template <class T>
struct BiNodeTag   //用于后序遍历二叉树非递归实现(2次进栈)的结点结构
{
  char tag;
  BiNode<T> *pt;
};

template <class T>
class BiTree
{ //二叉树类
public:
    BiTree( );       //构造函数,键盘输入扩展二叉树的前序序列构造二叉树
    BiTree(char *s); //构造函数,由扩展二叉树的前序遍历序列s构造二叉树
    BiTree(string sp,string sm); //构造函数,由扩展二叉树的前序遍历序列sp,中序遍历序列sm构造二叉树
    ~BiTree(void);         //析构函数,释放二叉链表中各结点的存储空间
    BiNode<T>* Getroot();  //获得指向根结点的指针
    void PreOrder(BiNode<T> *root);     //前序遍历二叉树递归
    void PreOrder0(BiNode<T> *root);    //前序遍历二叉树非递归
    void InOrder(BiNode<T> *root);      //中序遍历二叉树递归
    void InOrder0(BiNode<T> *root);    //中序遍历二叉树非递归
    void PostOrder(BiNode<T> *root);    //后序遍历二叉树递归
    void PostOrder0(BiNode<T> *root);    //后序遍历二叉树非递归
    void PostOrder1(BiNode<T> *root);    //后序遍历二叉树非递归1,只进一次栈
    void LevelOrder(BiNode<T> *root);   //层序遍历二叉树
private:
    BiNode<T> *root;         //指向根结点的头指针
    BiNode<T> *Creat();     //无参构造函数调用
    BiNode<T> *Creat(char *s);     //有参构造函数调用
    BiNode<T> *Creat(string sp,string sm);     //有参构造函数调用
    void Release(BiNode<T> *root);   //析构函数调用
};


/*
 *前置条件:二叉树不存在
 *输    入:无
 *功    能:构造一棵二叉树
 *输    出:无
 *后置条件:产生一棵二叉树
 */
template<class T>
BiTree<T>::BiTree(char *s )
{
    m=0;
    root = Creat(s);
}
template<class T>
BiTree<T>::BiTree( )
{
    root = Creat();
}
template<class T>
BiTree<T>::BiTree(string sp,string sm )
{
    root = Creat(sp,sm);
}
/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:释放二叉链表中各结点的存储空间
 *输    出:无
 *后置条件:二叉树不存在
 */
template<class T>
BiTree<T>::~BiTree(void)
{
    Release(root);
}
/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:获取指向二叉树根结点的指针
 *输    出:指向二叉树根结点的指针
 *后置条件:二叉树不变
 */
template<class T>
BiNode<T>* BiTree<T>::Getroot( )
{
    return root;
}
/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:前序遍历二叉树
 *输    出:二叉树中结点的一个线性排列
 *后置条件:二叉树不变
 */
template<class T>
void BiTree<T>::PreOrder(BiNode<T> *root)
{
    if(root==NULL)  return;
    else{
        cout<<root->data<<" ";
        PreOrder(root->lchild);
        PreOrder(root->rchild);
    }
}

/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:中序遍历二叉树
 *输    出:二叉树中结点的一个线性排列
 *后置条件:二叉树不变
 */
template <class T>
void BiTree<T>::InOrder (BiNode<T> *root)
{
    if (root==NULL)  return;      //递归调用的结束条件
    else{
        InOrder(root->lchild);    //中序递归遍历root的左子树
        cout<<root->data<<" ";    //访问根结点的数据域
        InOrder(root->rchild);    //中序递归遍历root的右子树
    }
}
/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:后序遍历二叉树
 *输    出:二叉树中结点的一个线性排列
 *后置条件:二叉树不变
 */
template <class T>
void BiTree<T>::PostOrder(BiNode<T> *root)
{
    if (root==NULL)   return;       //递归调用的结束条件
    else{
        PostOrder(root->lchild);    //后序递归遍历root的左子树
        PostOrder(root->rchild);    //后序递归遍历root的右子树
        cout<<root->data<<" ";      //访问根结点的数据域
    }
}

/*
 *前置条件:二叉树已存在
 *输    入:无
 *功    能:层序遍历二叉树
 *输    出:二叉树中结点的一个线性排列
 *后置条件:二叉树不变
 */
template <class T>
void BiTree<T>::LevelOrder(BiNode<T> *root)
{
    const int MaxSize = 100;

    int front = 0;
    int rear = 0;  //采用顺序队列,并假定不会发生上溢

    BiNode<T>* Q[MaxSize];
    BiNode<T>* q;

    if (root==NULL) return;
    else{
        Q[rear++] = root;
        while (front != rear)
        {
            q = Q[front++];
             cout<<q->data<<" ";
            if (q->lchild != NULL)    Q[rear++] = q->lchild;
            if (q->rchild != NULL)    Q[rear++] = q->rchild;
        }
    }
}

/*
 *前置条件:空二叉树
 *输    入:数据ch;
 *功    能:初始化一棵二叉树,构造函数调用
 *输    出:无
 *后置条件:产生一棵二叉树
 */
//int m=0;
template <class T>
BiNode<T>* BiTree<T>::Creat(char *s)
{
    BiNode<T>* root;
    char ch=s[m++];
    //cout<<"请输入创建一棵二叉树的结点数据"<<endl;
    //cin>>ch;
    if (ch=='#') root = NULL;
    else{
         root = new BiNode<T>;       //生成一个结点
         root->data=ch;
         root->lchild = Creat(s );    //递归建立左子树
         root->rchild = Creat(s );    //递归建立右子树
    }
    return root;
}
template <class T>
BiNode<T>* BiTree<T>::Creat(string sp,string sm)
{
    BiNode<T>* root=NULL;
    if(sp.length() > 0)
    {
        root=new BiNode<T> ;
        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 <class T>
BiNode<T>* BiTree <T>::Creat()
{   BiNode<T>* root;
    char ch;
    cout<<"Input a char: ";
    cin>>ch;
    if (ch=='#')     root=NULL;
    else {
        root=new BiNode<T>;
        root->data=ch;
        root-> lchild=Creat();
        root-> rchild=Creat();
    }
 return root;
}

/*
 *前置条件:二叉树已经存在
 *输    入:无
 *功    能:释放二叉树的存储空间,析构函数调用
 *输    出:无
 *后置条件:二叉树不存在
 */
template<class T>
void BiTree<T>::Release(BiNode<T>* root)
{
  if (root != NULL){
      Release(root->lchild);   //释放左子树
      Release(root->rchild);   //释放右子树
      delete root;
  }
}

template<class T>
void BiTree<T>::PreOrder0(BiNode<T> *root)
{//前序遍历二叉树非递归
    const int MaxStackSize=100;
    BiNode<T> *S[MaxStackSize];
    int top= -1;   // 构造空栈,采用顺序栈,并假定不会发生上溢
    while (root!=NULL||top!= -1)
     {
         while (root!= NULL)
         {
             cout<<root->data;
             S[++top]=root;;
             root=root->lchild;
         }
         if (top!= -1) {
             root=S[top--];
             root=root->rchild;
         }
     }
}
template<class T>
void BiTree<T>::InOrder0(BiNode<T> *root)
{//中序遍历二叉树非递归
    const int MaxStackSize=100;
    BiNode<T> *S[MaxStackSize];
    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->data;
             root=root->rchild;
         }
     }
}
template<class T>
void BiTree<T>::PostOrder0(BiNode<T> *root)
{//二叉树后序遍历非递归 2次入栈
    const int MaxStackSize=100;
    BiNodeTag<T> S[MaxStackSize];
    BiNodeTag<T> p;
    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<<p.pt->data;//root=NULL;
          }
          }
     }
}

template<class T>
void BiTree<T>::PostOrder1(BiNode<T> *root)//后序遍历二叉树非递归1,只进一次栈
{
    //二叉树后序遍历非递归 一次入栈:
    //后序遍历在中序的双层循环的基础上需要加入一个记录记录上一次出栈的节点。步骤如下:
    //1、如果栈顶元素非空且左孩子存在,将左孩子入栈,重复该过程。若不存在则进入第2步(该过程和中序遍历一致)
    //2、判断上一次出栈节点是否当前节点的右孩子,或者当前节点是否存在右孩子,满足任一条件,将当前节点输出,并出栈。否则将右节点压栈。跳至第1步
    const int MaxStackSize=100;
    BiNode<T> *S[MaxStackSize];
    int top= -1;   // 构造空栈,采用顺序栈,并假定不会发生上溢
    if(root == NULL) return;
    S[++top]=root;
    BiNode<T>* lastpop = NULL;
    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<<S[top]->data;
                lastpop = S[top--];
            }
            else if(S[top]->rchild != NULL)
            {
                top++;
                S[top]=S[top-1]->rchild;
                break;
            }
        }
    }
}
template <class T>
void Count(BiNode<T> *root,int &n)  //n为全局量并已初始化为0
{//求二叉树结点个数
    if (root) {
         Count(root->lchild,n);
         n++;
         Count(root->rchild,n);
   }
}
template <class T>
int CountNodes(BiNode<T> *root){//求二叉树结点个数
    int n=0;
    Count(root,n);
    return n;
    }
template <class T>
int num_of_nodes(BiNode<T> *t)//求二叉树结点个数
{
    if(t == NULL)return 0;
    int nl=num_of_nodes(t->lchild);
    int nr=num_of_nodes(t->rchild);
    return 1+nl+nr;
}
template <class T>
void PreOrderleaf(BiNode<T> *root)//前序遍历顺序输出二叉树叶子结点
{
    if (root) {
        if (!root->lchild && !root->rchild)
               cout<<root->data;
        PreOrderleaf(root->lchild);
        PreOrderleaf(root->rchild);
   }
}
template<class T>
void InOrder0leaf(BiNode<T> *root)
{   //非递归中序遍历顺序输出二叉树叶子结点
    const int MaxStackSize=100;
    BiNode<T> *S[MaxStackSize];
    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->data;
             root=root->rchild;
         }
     }
}
template <class T>
int  Depth(BiNode<T> *root)
{//求二叉树的高度
    if (root==NULL) return 0;
    else {
         int hl=Depth(root->lchild);
         int hr=Depth(root ->rchild);
         return hl>hr?hl+1:hr+1;
    }
}
template <class T>
int CountDC(BiNode<T> *root)
//计算二叉树中有所有叶子结点的和。
{
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()
{    BiNode<char>* root;
    BiTree<char> bt; //创建一棵二叉树
    root = bt.Getroot( );  //获取指向根结点的指针
    cout<<"------前序遍历------ "<<endl;
    bt.PreOrder(root);
    cout<<endl;
    bt.PreOrder0(root);
    cout<<endl;
    cout<<"------中序遍历------ "<<endl;
    bt.InOrder(root);
    cout<<endl;
    bt.InOrder0(root);
    cout<<endl;
    cout<<"------后序遍历------ "<<endl;
    bt.PostOrder(root);
    cout<<endl;
    bt.PostOrder0(root);
    cout<<endl;
    cout<<"------层序遍历------ "<<endl;
    bt.LevelOrder(root);
    cout<<endl;
    cout<<"Number of nodes="<<CountNodes(root)<<endl;
    cout<<"Number of nodes="<<num_of_nodes(root)<<endl;
    cout<<"Leaf-nodes are ";
    PreOrderleaf(root);
    cout<<endl<<"Leaf-nodes are ";
    InOrder0leaf(root);
    cout<<endl<<"Depth="<<Depth(root)<<endl;

    BiTree<char> bt1("ABD#EI##F##CG#H####"); //创建一棵二叉树
    //BiNode<string>* root;  //获取指向根结点的指针
    root = bt1.Getroot( );

    cout<<"------前序遍历------ "<<endl;
    bt1.PreOrder(root);
    cout<<endl;
    bt1.PreOrder0(root);
    cout<<endl;
    cout<<"------中序遍历------ "<<endl;
    bt1.InOrder(root);
    cout<<endl;
    bt1.InOrder0(root);
    cout<<endl;
    cout<<"------后序遍历------ "<<endl;
    bt1.PostOrder(root);
    cout<<endl;
    bt1.PostOrder0(root);
    cout<<endl;
    cout<<"------层序遍历------ "<<endl;
    bt1.LevelOrder(root);
    cout<<endl;
    /*n=0;
    Count(root);
    cout<<"Number of nodes="<<n<<endl;*/
    cout<<"Number of nodes="<<CountNodes(root)<<endl;
    cout<<"Leaf-nodes are ";
    PreOrderleaf(root);
    cout<<endl<<"Leaf-nodes are ";
    InOrder0leaf(root);
    cout<<endl<<"Depth="<<Depth(root)<<endl;
    cout<<CountDC(root)<<endl;

//    BiTree<char> bt2("DBEAFC","ABDECF"); //创建一棵二叉树
    BiTree<char> bt2("abdcef","dbacfe"); //创建一棵二叉树树
    root = bt2.Getroot( );  //获取指向根结点的指针
    cout<<"------前序遍历------ "<<endl;
    bt2.PreOrder(root);    cout<<endl;
    bt2.PreOrder0(root);    cout<<endl;
    cout<<"------中序遍历------ "<<endl;
    bt2.InOrder(root);    cout<<endl;
    bt2.InOrder0(root);    cout<<endl;
    cout<<"------后序遍历------ "<<endl;
    bt2.PostOrder(root);cout<<endl;
    bt2.PostOrder0(root);cout<<endl;
    bt2.PostOrder1(root);cout<<endl;
    cout<<endl;
    cout<<"------层序遍历------ "<<endl;
    bt2.LevelOrder(root);    cout<<endl;
    cout<<CountDC(root)<<endl;


    int x[] = { 5,29,7,8,14,23,3,11 };        // 权值集合
    element *hufftree=new element[2*8-1];    // 动态创建数组
    HuffmanTree(hufftree, x, 8);
    print(hufftree,15);

    return 0;
}

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值