数据结构实验5.二叉树的一些功能

1.实现的功能

(1)按先序遍历的方式输入二叉树
(2)二叉搜索树的方式插入节点
(3)前中后序遍历二叉树
(4)层序遍历二叉树
(5)普通搜索二叉树数据
(6)按搜索二叉树的方式搜索数据
(7)删除某个节点(若有两个孩子,左孩子插到原来的位置,将右孩子插到原左孩子的最近的度小于2的节点上,优先左孩子,所以用了之后就不能用6搜索了)。
(8)得到叶子的个数,可选是否输出叶子节点
(9)得到树的高度
(10)得到树的宽度
(11)输出所有从叶子到根的路径,可以容易的改成逆序。
(12)自定义结束符

2.依赖的头文件

“anotherQueue.h”

#ifndef __ANOTHERQUEUE_H__
#define __ANOTHERQUEUE_H__


template<typename T>
class Queue
{
    public:
    Queue()
    {
        maxsize = 10;
        data = new T[maxsize];
        head = tail = 0;
        is_full = 0;
    }
    Queue(int n)
    {
        maxsize = n;
        data = new T[maxsize];
        head = tail = 0;
        is_full = 0;//初始为否
    }
    void push(T d);
    T pop();
    T popStack();
    T getHead(){return data[head];}
    bool isEmpty(){return ((head == tail) && ! is_full);}
    bool isFull(){return is_full;}
private:
    T *data;
    int head;
    int tail;
    bool is_full;
    int maxsize;
};

template<typename T>
void Queue<T>::push(T d)
{
    if(is_full) return;
    data[tail] = d;
    tail = (tail+1) % maxsize;
    if(tail == head) is_full = 1;
}

template<typename T>
T Queue<T>::pop()
{
    if(isEmpty()) return(T) 0;
    T rslt = data[head];
    head = (head+1) % maxsize;
    return rslt;
}

template<typename T>
T Queue<T>::popStack()
{
    if(isEmpty()) return(T) 0;
    tail = (tail-1) % maxsize;
    if(tail < 0)//归位
        tail = maxsize - 1;
    T rslt = data[tail];
    return rslt;
}

#endif

3.本体

“BiTree.h”

#ifndef __BITREE_H__
#define __BITREE_H__

#define nullptr 0
#include<iostream>
#include"anotherQueue.h"

using namespace std;

template<typename T>
struct Node
{
    Node()
    {
        data = 0;
        lchild = rchild = nullptr;
    }
    Node(T d)
    {
        data = d;
        lchild = rchild = nullptr;
    }
    T data;
    Node<T> *lchild;
    Node<T> *rchild;
};

template<typename T>
class BiTree
{
public:
     BiTree()
    {
        cout<<"请输入结束符";
        cin>>terminator;
        create(root);
    }
    void addNode();
    void preOrder(){preOrder(root);}
    void inOrder(){inOrder(root);}
    void postOrder(){postOrder(root);}
    void queueLevelOrder(){queueLevelOrder(root);};
    Node<T> *srchData(T srch_data){return srchData(root,srch_data);}
    Node<T> *srchDataBST(T srch_data){return srchDataBST(root,srch_data);}
    void delData(T del_data);
    int getLeaveNum(int show_leave){return getLeaveNum(root,show_leave);}
    int getTreeHight(){return getTreeHight(root);}
    int getTreeWidth(){return getTreeWidth(root);}
    void showLeaveToRootWay(){showLeaveToRootWay(root);}
private:
    void srchTreeAddNode(Node<T> *&root,T d);
    void create(Node<T> *&root);
    void preOrder(Node<T> *root);
    void inOrder(Node<T> *root);
    void postOrder(Node<T> *root);
    void levelOrder(Node<T> *root);
    void queueLevelOrder(Node<T> *root);
    Node<T> *srchData(Node<T> *root,T srch_data);
    Node<T> *srchDataBST(Node<T> *root,T srch_data);
    Node<T> *srchSingle(Node<T> *root);
    int delData(Node<T> *&root,T del_data);
    void insData(Node<T> *&root,T ins_data,int ins_pos);
    int getLeaveNum(Node<T> *root,int show_leave);
    int getTreeHight(Node<T> *root);
    int getTreeWidth(Node<T> *root);
    void showLeaveToRootWay(Node<T> *root);

    Queue<Node<T>*> order_helper;
    Node<T> *root;
    T terminator;

};

template<typename T>
void BiTree<T>::addNode()
{
    T d;
    while(1)
    {
        cin>>d;
        if(d == terminator)
            break;
        srchTreeAddNode(root,d);
    }
}

template<typename T>
void BiTree<T>::delData(T del_data)
{
        Node<T> *ptoroot = new Node<T>;//声明一个头节点左子树指针指向原树的根
        ptoroot->lchild = root;
        while(delData(ptoroot,del_data))
        {
            if(root)
            ptoroot->lchild = root;
        }
        delete ptoroot;//释放头结点
}

template<typename T>
void BiTree<T>::srchTreeAddNode(Node<T> *&root,T d)
{
    if(root == nullptr)
    {//若无数据
        root = new Node<T>(d);
        return;
    }
    if(root->data > d)
    {//大于
        srchTreeAddNode(root->lchild,d);
        return;
    }
    if(root->data == d)
    {//等于
        return;
    }
    if(root->data < d)
    {//小于
        srchTreeAddNode(root->rchild,d);
        return;
    }
    
}

template<typename T>
void BiTree<T>::create(Node<T> *&root)
{
    T d;
    cin>>d;
    if(d == terminator)
    {
        root = nullptr;
        return;
    }
    root = new Node<T>(d);
    create(root->lchild);
    create(root->rchild);
}

template<typename T>
void BiTree<T>::preOrder(Node<T> *root)
{
    if(root == nullptr)
        return;
    cout<<root->data<<' ';
    preOrder(root->lchild);
    preOrder(root->rchild);
}

template<typename T>
void BiTree<T>::inOrder(Node<T> *root)
{
    if(root == nullptr)
        return;
    inOrder(root->lchild);
    cout<<root->data<<' ';
    inOrder(root->rchild);
}

template<typename T>
void BiTree<T>::postOrder(Node<T> *root)
{
    if(root == nullptr)
        return;
    postOrder(root->lchild);
    postOrder(root->rchild);
    cout<<root->data<<' ';
}

template<typename T>
void BiTree<T>::queueLevelOrder(Node<T> *root )
{
    while(root)
    {
        cout<<root->data<<' ';
        if(root->lchild)order_helper.push(root->lchild);
        if(root->rchild)order_helper.push(root->rchild);
        root = order_helper.pop();
    }
}

template<typename T>
Node<T> *BiTree<T>::srchData(Node<T> *root,T srch_data)
{
    Node<T> *pt;
    if(root == nullptr)
        return root;
    if(root -> data == srch_data)
        return root;
    pt = srchData(root->lchild,srch_data);
    if(pt)
        return pt; 
    pt = srchData(root->rchild,srch_data);
    if(pt)
        return pt; 
    
}

template<typename T>
Node<T> *BiTree<T>::srchDataBST(Node<T> *root,T srch_data)
{
    Node<T> *pt;
    cout<<1;
    if(root == nullptr)
        return root;
    if(root->data < srch_data)
    {
        pt = srchDataBST(root->rchild,srch_data);
        if(pt)
            return pt;
    }
    if(root->data == srch_data)
    {
        return root;
    }
    if(root->data > srch_data)
    {
        pt = srchDataBST(root->lchild,srch_data);
        if(pt)
            return pt;
    }
    
}

template<typename T>
Node<T> *BiTree<T>::srchSingle(Node<T> *root)
{
    Node<T> *pt;
    if(root-> lchild == NULL ||root -> rchild == NULL)
    {
        return root;
    }
    pt = srchSingle(root -> lchild);
    if(pt)
        return pt;
    pt = srchSingle(root -> rchild);
    if(pt)
        return pt;
}

template<typename T>
int BiTree<T>::delData(Node<T> *&root,T del_data)
{//删除一个值为del_data 的节点,此处使用不传入双亲节点的方法
    if(root == nullptr)
        return 0;
    if(root->lchild)
    {//先看当前节点的的左孩子
        if(root->lchild -> data == del_data)
        {//查找到要删除的节点
            if(!(root->lchild -> lchild) && !(root->lchild ->rchild))
            {//若该节点是叶子节点
                delete root->lchild;
                if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
                    this->root = NULL;
                root->lchild = NULL;
                
                return 1;
            }
            if(root->lchild ->lchild && root->lchild ->rchild)
            {//若该节点有两个孩子,将左孩子接到原位置,为右孩子找新父母,且新父母在当前树的子树下
                Node<T> *pt = root -> lchild -> lchild;//暂存左孩子
                Node<T> *new_parent = srchSingle(root->lchild);//找到不是两个孩子的父母,处理右节点    注:此处必把要删除的节点的右子树接到左子树最近的空枝上
                if(new_parent->lchild)
                {//若新父母有左孩子
                    new_parent->rchild = root -> lchild ->rchild;
                }
                else
                {//没有左孩子
                    new_parent->lchild = root ->lchild ->rchild;
                }
                delete root -> lchild;//删掉左孩子
                if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
                    this->root = pt;
                root -> lchild = pt;//连接左孩子
                return 1;
            }
            if(root->lchild ->lchild || root->lchild ->rchild)
            {//若该节点有一个孩子,有两个孩子的情况在上面处理了,所以不会出现在这里
                if(root->lchild ->lchild)
                {//是左孩子
                    Node<T> *pt = root -> lchild ->lchild;
                    delete root -> lchild;
                    if(root->lchild == this->root)//由于之前将原root视为辅助头结点的左子树,此处若删除的是树根,就把root重新赋值为
                    this->root = pt;
                    root -> lchild = pt;//替换
                    return 1;
                }
                else
                {//右孩子
                    Node<T> *pt = root -> lchild ->rchild;
                    delete root -> lchild;
                    root -> lchild = pt;//替换
                    return 1;
                }
            }
        }
    }
    if(root->rchild)
    {//再看当前节点的的右孩子
        if(root->rchild->data == del_data)
        {//查找到要删除的节点
            if(!(root->rchild -> lchild) && !(root->rchild ->rchild))
            {//若该节点是叶子节点
                delete root->rchild;
                root->rchild = NULL;
                return 1;
            }
            if(root->rchild ->lchild && root->rchild ->rchild)
            {//若该节点有两个孩子,将左孩子接到原位置,为右孩子找新父母,且新父母在当前树的子树下
                Node<T> *pt = root -> rchild -> lchild;//暂存左孩子
                Node<T> *new_parent = srchSingle(root->rchild);//找到不是两个孩子的父母,处理右节点
                if(new_parent->lchild)
                {//若新父母有左孩子
                    new_parent->rchild = root -> rchild ->rchild;
                }
                else
                {//有右孩子
                    new_parent->lchild = root ->rchild ->rchild;
                }
                delete root -> rchild;//删掉右孩子
                root -> rchild = pt;//连接右孩子
                return 1;
            }
            if(root->rchild ->lchild || root->rchild ->rchild)
            {//若该节点有一个孩子,有两个孩子的情况在上面处理了,所以不会出现在这里
                if(root->rchild ->lchild)
                {//是左孩子
                    Node<T> *pt = root -> rchild ->lchild;
                    delete root -> rchild;
                    root -> rchild = pt;//替换
                    return 1;
                }
                else
                {//右孩子
                    Node<T> *pt = root -> rchild ->rchild;
                    delete root -> rchild;
                    root -> rchild = pt;//替换
                    return 1;
                }
            }
        }
    }
    delData(root -> lchild,del_data);
    delData(root -> rchild,del_data);
    return 0;
}


template<typename T>
int BiTree<T>::getLeaveNum(Node<T> *root,int show_leave)
{
    int num;
    if(root == nullptr)
        return 0;
    if(root->lchild == nullptr && root->rchild == nullptr)
    {
        if(show_leave)
            cout<<root->data<<' ';
        return 1;
    }
    num = getLeaveNum(root->lchild,show_leave) + getLeaveNum(root->rchild,show_leave);
    return num;
}

template<typename T>
int BiTree<T>::getTreeHight(Node<T> *root)
{
    int l_hight,r_hight;
    if(root == nullptr)
        return 0;
    if(root->lchild == nullptr &&root->rchild == nullptr)
        return 1;
    l_hight = getTreeHight(root->lchild);
    r_hight = getTreeHight(root->rchild);
    return ((l_hight>r_hight?l_hight:r_hight)+1);//算上自己的高度
}

template<typename T>
int BiTree<T>::getTreeWidth(Node<T> *root)
{
    if(root == nullptr)
        return 0;
    int this_level_node_left = 1;//本层剩余的节点数
    int max_width = this_level_node_left;
    int next_level_node_count = 0;//下一层的节点数
    order_helper.push(root);//首先入栈整棵树的根节点
    while(!order_helper.isEmpty())
    {
        while(this_level_node_left)
        {
            root = order_helper.pop();
            if(root->lchild)
            {
                order_helper.push(root->lchild);
                next_level_node_count++;
            }
            if(root->rchild)
            {
                order_helper.push(root->rchild);
                next_level_node_count++;
            }
                this_level_node_left--;
            
        }
        max_width = max_width > next_level_node_count?max_width:next_level_node_count;
        this_level_node_left = next_level_node_count;
        next_level_node_count = 0;
    }
    return max_width;
}

template<typename T>
void BiTree<T>::showLeaveToRootWay(Node<T> *root)
{
    if(root == nullptr)//遍历结束
        return;
    if(root->lchild == nullptr && root->rchild == nullptr)
    {//是叶子节点
        order_helper.push(root);
        int count = 0,i = 0;
        Node<T> **printway = new Node<T>*[getTreeHight()];
        while(!order_helper.isEmpty())
        {//得到路径
            printway[count++] = order_helper.popStack();
        }
        i = count-1;
        while(i>=0)
        {//再塞回去
            order_helper.push(printway[i--]);
        }
        for(i = 0;i < count;i++)
        {//输出路径
            cout<<printway[i]->data<<' ';
        }
        cout<<endl;
        order_helper.popStack();
        return;
    }
    order_helper.push(root);
    if(root->lchild)
    {
        showLeaveToRootWay(root->lchild);
    }
    if(root->rchild)
    {
        showLeaveToRootWay(root->rchild);
    }
    order_helper.popStack();
}
#endif

4. 一个简单的测试用代码

#include<iostream>
#include<conio.h>

#include"anotherQueue.h"
#include"BiTree.h"
#define nullptr 0

using namespace std;
int main()
{
    BiTree<int> tree1;
    Node<int> *psrch_ans_node;
    int srch_data,del_data;

    tree1.addNode();
    cout<<"先序遍历"<<endl;
    tree1.preOrder();
    cout<<endl<<"中序遍历"<<endl;
    tree1.inOrder(); 
    cout<<endl<<"后序遍历"<<endl;
    tree1.postOrder();
    cout<<endl<<"层序遍历"<<endl;
    tree1.queueLevelOrder();
    cout<<endl<<"请输入要查找的数据:";
    cin>>srch_data;
    psrch_ans_node = tree1.srchDataBST(srch_data);
    if(psrch_ans_node)
        cout<<psrch_ans_node->data;
    //cout<<endl<<"请输入要删除的数据:";
    //cin>>del_data;
    //tree1.delData(del_data);
    //cout<<"先序遍历"<<endl;
    //tree1.preOrder();
    cout<<endl<<"树叶们"<<endl;
    tree1.getLeaveNum(1);
    cout<<"\n一共有 "<<tree1.getLeaveNum(0)<<" 片树叶"<<endl;
    //cout<<endl<<tree1.getTreeHight();
    //cout<<endl<<tree1.getTreeWidth();
    tree1.showLeaveToRootWay();

    getch();
    return 0;
}

代码执行效果
运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值