上机作业之树:递归算法在二叉树中的简单应用

二叉树习题 3.5

  1. 设一棵二叉树以二叉链表表示,试编写有关二叉树的递归算法:
    1) 统计二叉树中度为1的结点个数;
    2) 统计二叉树中度为2的结点个数;
    3) 统计二叉树中度为0(叶节点)的结点个数;
    4) 统计二叉树的高度;
    5) 统计二叉树的宽度,即在二叉树的各层上具有结点数最多的那一层上结点总数;
    6) 计算二叉树中各结点中最大元素的值;
    7) 交换每个结点的左孩子结点和右孩子结点;
    8) 从二叉树中删去所有叶节点;
  2. 编写算法判别给定二叉树是否为完全二叉树。
//
//  main.cpp
//  3.5
//
//  Created by Cyril on 2016/11/9.
//  Copyright © 2016年 Cyril. All rights reserved.
//

#include <iostream>
#include <queue>
#define MIN -100000000
using namespace std;
//二叉树结点的定义
template <class T>
class BT;

template <class T>
class BTNode
{
    friend class BT<T>;
private:
    T data;
    BTNode *lChild;
    BTNode *rChild;
public:
    BTNode();
    BTNode(T& d);//给定数据域的值得构造函数
    BTNode(T& d, BTNode *l, BTNode *r);//给定数据域以及左右孩子的构造函数
    BTNode<T> *GetLChild();//返回左孩子结点的指针
    BTNode<T> *GetRChild();//返回右孩子结点的指针
    void SetLChild(BTNode<T> *l);//设置左孩子结点
    void SetRChild(BTNode<T> *r);//设置右孩子结点
    ~BTNode(){}
    T GetValue();//返回该节点数据值
    bool SetValue(T& val);//设置该点数据值
    bool IsLeaf();//判断是否为叶子结点
    void DisplayNode();//输出结点
};
template <class T>
BTNode<T>::BTNode()
{
    lChild=rChild=NULL;
}
template <class T>
BTNode<T>::BTNode(T& d)//给定数据域的值得构造函数
{
    lChild=rChild=NULL;
    data=d;
}
template <class T>
BTNode<T>::BTNode(T& d, BTNode *l, BTNode *r)//给定数据域以及左右孩子的构造函数
{
    lChild=l;
    rChild=r;
    data=d;
}
template <class T>
BTNode<T>* BTNode<T>:: GetLChild()//返回左孩子结点的指针
{
    return lChild;
}
template <class T>
BTNode<T>* BTNode<T>:: GetRChild()//返回右孩子结点的指针
{
    return rChild;
}
template <class T>
void BTNode<T>:: SetLChild(BTNode<T> *l)//设置左孩子结点
{
    lChild=l;
}
template <class T>
void BTNode<T>:: SetRChild(BTNode<T> *r)//设置右孩子结点
{
    rChild=r;
}
template <class T>
T BTNode<T>:: GetValue()//返回该节点数据值
{
    return data;
}
template <class T>
bool BTNode<T>:: SetValue(T& val)//设置该点数据值
{
    this->data=val;
    return true;
}
template <class T>
bool BTNode<T>:: IsLeaf()//判断是否为叶子结点
{
    if(lChild==NULL&&rChild==NULL)
        return true;
    else
        return false;
}
template <class T>
void BTNode<T>:: DisplayNode()//输出结点
{
    cout<<"该结点的数据为: "<<data<<endl;
}
//二叉树类的定义
template <class T>
class BT
{
private:
    BTNode<T> *root;//二叉树的根节点
    int s;//用于记录结点的个数
public:
    BT(){root=NULL;}
    ~BT(){}
    void NewTree();//创建新树
    BTNode<T>* SetSubTree();//创建子树并返回子树的根结点地址
    bool IsEmpty();//判断是否为空树
    BTNode<T>* GetRoot();//返回根节点
    bool GetParent(BTNode<T> *cur);//返回当前结点的父节点.(未实现)
    bool GetLSibling(BTNode<T> *cur);//返回当前结点的左兄弟.(未实现)
    bool GetRSibling(BTNode<T> *cur);//返回当前结点的右兄弟.(未实现)
    bool LevelOrder(BTNode<T> *r);//广度优先遍历
    bool PreOrder(BTNode<T> *r);//前序遍历
    bool DeleteNode(BTNode<T> *r);//删除以r为根结点的子树.(未实现)
    void Display();//输出树
    void RecDisplay(BTNode<T> *t);//用于输出树时的循环迭代

    int GetDegree(int num);//计算二叉树中度为num的结点个数,并返回
    int CalDegree2(BTNode<T> *r);//计算结点为2的结点个数,并返回
    int CalDegree1(BTNode<T> *r);//计算结点为1的结点个数,并返回
    int CalDegree0(BTNode<T> *r);//计算结点为0的结点个数,并返回

    int GetHeight(BTNode<T> *r);//计算二叉树的高度,并返回
    void CalWidth(BTNode<T> *r,int *count,int depth);//递归计算二叉树的宽度
    int GetWidth();//计算二叉树宽度

    T GetMax(BTNode<T> *r);//计算二叉树中结点的最大元素,并返回
    void SwapChildren(BTNode<T> *r);//交换每一个结点的左孩子结点和右孩子结点
    void DeleteLeaf(BTNode<T> *r);//删除叶节点

    bool IsCompleteBT();//判断是否为完全二叉树
};
template <class T>
void BT<T>::NewTree()//创建新树
{
    cout<<"请输入根结点的数据:"<<endl;
    root=SetSubTree();
}
template <class T>
BTNode<T>* BT<T>::GetRoot()//返回根节点
{
    return root;
}
template <class T>
BTNode<T>* BT<T>:: SetSubTree()//创建子树并返回子树的根结点地址
{
    T t;
    cin>>t;
    BTNode<T> *p;
    if(t=='#')
        return NULL;//返回空指针
    else
    {
        p=new BTNode<T>;
        p->SetValue(t);
        //cout<<"成功读入"<<t<<endl;
        cout<<"请输入左孩子结点的数据:(输入‘#’则表示不存在左孩子结点)"<<endl;
        p->SetLChild(SetSubTree());
        cout<<"请输入右孩子结点的数据:(输入‘#’则表示不存在右孩子结点)"<<endl;
        p->SetRChild(SetSubTree());
        return p;
    }
}
template <class T>
bool BT<T>:: IsEmpty()//判断是否为空树
{
    return !root;
}
template <class T>
bool BT<T>:: LevelOrder(BTNode<T> *r)//广度优先遍历
{
    queue<BTNode<T>*> NodeQueue;
    BTNode<T> *p=root;
    if(p)
        NodeQueue.push(p);
    while (!NodeQueue.empty())
    {
        p=NodeQueue.front();
        //...访问p指针指向的结点
        //样例操作:广度优先输出树 cout<<p->data<<' ';
        NodeQueue.pop();
        if(p->lChild)
            NodeQueue.push(p->lChild);
        if(p->rChild)
            NodeQueue.push(p->rChild);
    }
    return true;
}
template <class T>
bool BT<T>:: PreOrder(BTNode<T> *r)//前序遍历
{
    if(r)
    {
        //...访问r指针指向的结点
        //样例操作:深度优先输出树 cout<<r->data<<' ';
        PreOrder(r->lChild);
        PreOrder(r->rChild);
        return true;
    }
    return false;
}
template <class T>
void BT<T>:: Display()
{
    RecDisplay(root);
    cout<<endl;
}
template <class T>
void BT<T>:: RecDisplay(BTNode<T> *t)
{
    if(t!=NULL)
    {
        cout<<t->data;
        if(t->lChild||t->rChild)
        {
            cout<<'(';
            RecDisplay(t->lChild);
            cout<<',';
            if(t->rChild)
                RecDisplay(t->rChild);
            else
                cout<<'#';
            cout<<')';
        }
    }
    else
    {
        cout<<'#';
    }
}

template <class T>
int BT<T>:: GetDegree(int num)//计算二叉树中度为num的结点个数,并返回
{
    s=0;
    if(num==2)
        return CalDegree2(root);
    else if(num==1)
        return CalDegree1(root);
    else if(num==0)
        return CalDegree0(root);
    else
        return -1;//不合法就返回-1
}
template <class T>
int BT<T>:: CalDegree2(BTNode<T> *r)//计算结点为2的结点个数,并返回
{
    if(!r)
        return 0;//空指针返回0
    s=(r->lChild!=NULL)&&(r->rChild!=NULL);
    return s+CalDegree2(r->lChild)+CalDegree2(r->rChild);
}
template <class T>
int BT<T>:: CalDegree1(BTNode<T> *r)//计算结点为1的结点个数,并返回
{
    if(!r)
        return 0;//空指针返回0
    s=(r->lChild!=NULL&&r->rChild==NULL)||(r->lChild==NULL&&r->rChild!=NULL);//异或算法
    return s+CalDegree1(r->lChild)+CalDegree1(r->rChild);
}
template <class T>
int BT<T>:: CalDegree0(BTNode<T> *r)//计算结点为0的结点个数,并返回
{
    if(r==NULL)
        return 0;//空指针返回1
    s=(r->lChild==NULL)&&(r->rChild==NULL);
    return s+CalDegree0(r->lChild)+CalDegree0(r->rChild);
}

template <class T>
int BT<T>:: GetHeight(BTNode<T> *r)//计算二叉树的高度,并返回
{
    if(!r)
        return 0;
    int left=GetHeight(r->lChild)+1;
    int right=GetHeight(r->rChild)+1;
    return (left>right)?left:right;
}
template <class T>
void BT<T>:: CalWidth(BTNode<T> *r,int *count,int depth)//递归计算二叉树的宽度
{
    if(!r)
        return ;
    count[depth]++;
    CalWidth(r->lChild,count,depth+1);
    CalWidth(r->rChild,count,depth+1);
}
template <class T>
int BT<T>:: GetWidth()
{
    int de=GetHeight(root);
    int *count=new int [de];
    for(int i=0;i<de;i++)
        count[i]=0;
    CalWidth(root,count,0);
    int max=0;
    for(int i=0;i<de;i++)
        max=((count[i]>max)?count[i]:max);
    return max;
}
template <class T>
T BT<T>:: GetMax(BTNode<T> *r)//计算二叉树中结点的最大元素,并返回
{
   // cout<<r<<endl;
    if(r)
    {
        T left=GetMax(r->lChild);
        T current=r->data;
        T right=GetMax(r->rChild);
        T max=((left>right)?left:right);
        return ((current>max)?current:max);
    }
    else
        return MIN;
}
template <class T>
void BT<T>::SwapChildren(BTNode<T> *r)//交换每一个结点的左孩子结点和右孩子结点
{
    if(!r)
        return;
    BTNode<T> *temp;
    temp=r->lChild;
    r->lChild=r->rChild;
    r->rChild=temp;
    SwapChildren(r->lChild);
    SwapChildren(r->rChild);
}
template <class T>
void BT<T>:: DeleteLeaf(BTNode<T> *r)//删除叶节点
{
    if(!r)
        return;
    if(!root->lChild&&!root->rChild)
    {
        delete root;
        root=NULL;
    }
    if(r->lChild)
    {
        if(!r->lChild->lChild&&!r->lChild->rChild)
        {
            delete r->lChild;
            r->lChild=NULL;
        }
        else
            DeleteLeaf(r->lChild);
    }
    if(r->rChild)
    {
        if(!r->rChild->lChild&&!r->rChild->rChild)
        {
            delete r->rChild;
            r->rChild=NULL;
        }
        else
            DeleteLeaf(r->rChild);
    }
}
template <class T>
bool BT<T>:: IsCompleteBT()//判断是否为完全二叉树
{
    queue<BTNode<T>*> NodeQueue;
    int flag=1;
    NodeQueue.push(root);
    while(!NodeQueue.empty())
    {
        BTNode<T> *p=NodeQueue.front();
        NodeQueue.pop();
        if(p)
        {
            if(!flag) return false;
            NodeQueue.push(p->lChild);
            NodeQueue.push(p->rChild);
        }
        else
        {
            flag=0;
        }
    }
    return true;
}
int main()
{
    BT<char> Tree;
    Tree.NewTree();
    cout<<"该二叉树为"<<endl;
    Tree.Display();
    if(Tree.IsCompleteBT())
        cout<<"该二叉树为完全二叉树"<<endl;
    else
        cout<<"该二叉树不是完全二叉树"<<endl;
    for(int i=0;i<3;i++)
    {
        cout<<"二叉树中度为"<<i<<"的结点个数为:"<<Tree.GetDegree(i)<<endl;
    }
    cout<<"二叉树的高度为:"<<Tree.GetHeight(Tree.GetRoot())<<endl;
    cout<<"二叉树的宽度为:"<<Tree.GetWidth()<<endl;
    cout<<"二叉树的最大元素为:"<<Tree.GetMax(Tree.GetRoot())<<endl;
    cout<<"交换每一个左右孩子后的二叉树为:"<<endl;
    Tree.SwapChildren(Tree.GetRoot());
    Tree.Display();
    cout<<"删除叶节点后的二叉树为:"<<endl;
    Tree.DeleteLeaf(Tree.GetRoot());
    Tree.Display();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值