永发信息网

用c++来实现二叉树的遍历。

答案:1  悬赏:0  手机版
解决时间 2021-03-03 22:00
输入一棵树的各个节点信息,输出各种遍历的序列(先根、后根、中根、层次)。输入其中两种遍历序列,试图构造出该树,并输出其他两种遍历序列。
最佳答案
内容比较多,好好看看
单链表实现二叉树结构综合案例(使用类模板的方法)
--------------------二叉树节点类
#ifndef TREE_NODE
#define TREE_NODE
#include <iostream>
using namespace std;
template<typename T>
class Tree_Node
{
friend ostream& operator<< <T>(ostream& out,const Tree_Node& TN);//特例 这里不是:Tree_Node<T>&……模板参数移到前面去了
public:
    Tree_Node();
    Tree_Node<T>* searchNode(int _index); //判断当前节点,当前节点的孩子节点是否是要寻找的节点
    void DeleteNode();
    void Preorder();
    void Inorder();
    void Postorder();
    int m_iIndex; //节点的唯一索引值 
    T   m_TData;  //节点的数据类型在运行的时候指定
 //凡是要用到当前类的声明对象的都要加上模板参数
    Tree_Node<T>* m_pLchild; //左孩子指针
    Tree_Node<T>* m_pRchild; //右孩子指针
    Tree_Node<T>* m_pParent; //父指针
};
template<typename T>
ostream& operator<<(ostream& out,const Tree_Node<T>& TN) //模板参数又移到形参变量的地方了
{
    out<<TN.m_iIndex<<":"<<TN.m_TData<<endl;
    return out;
}
template<typename T>
Tree_Node<T>::Tree_Node() //实现构造函数,模板参数在类名中已经体现出来了
{
    this->m_iIndex =0;
    this->m_TData =NULL;
    this->m_pLchild =NULL;
    this->m_pRchild =NULL;
    this->m_pParent =NULL;
}
template<typename T>
Tree_Node<T>* Tree_Node<T>::searchNode(int _index) //根据节点的唯一索引值,查找节点,并返回节点的指针
{
    if (this->m_iIndex == _index) // 这个this指的是根节点这个对象
    {
        return this;
    }
    Tree_Node<T>* find_node =NULL;  //保存左子树和右子树查找到的结果
    if (this->m_pLchild !=NULL)
    {
        if (this->m_pLchild->m_iIndex == _index)
        {
            return this->m_pLchild;
        }
        else //当前节点的左孩子不是目标节点,再查找左孩子的后代,并返回结果,递归实现的关键
        {
            find_node = this->m_pLchild->searchNode(_index);
            //如果在左子树上找到了,则返回找到的节点,如果没有找到,再去右子树查找,在右子树查找的结果不管有没有都返回
            if (find_node != NULL)
            {
                return find_node;
            }
        }

    }
    if (this->m_pRchild !=NULL)
    {
        if (this->m_pRchild->m_iIndex == _index)
        {
            return this->m_pRchild;
        }else
        {
            find_node =this->m_pRchild->searchNode(_index);
            return find_node;  
        }
    }
    return NULL; // 要执行到这一步,就说明该节点既没有左孩子和右孩子,本身也不是待查找节点,就返回空指针了
}
template<typename T>
void Tree_Node<T>::DeleteNode()  // 删除节点,递归删除它的左孩子节点和右孩子节点
{
    if (this->m_pLchild !=NULL) //如果当前节点的左孩子节点不为空,则递归删除该左孩子节点和左孩子所有后代节点
    {
        this->m_pLchild->DeleteNode();
    }
    if (this->m_pRchild != NULL)//如果当前节点的右孩子节点不为空,则递归删除该子节点的所有后代
    {
        this->m_pRchild->DeleteNode();
    }
    //如果当前节点的父指针不为空,把这个指向关系置空
    if (this->m_pParent != NULL)
    {
        //判断当前节点是父节点的左孩子还是右孩子,以便置空父节点的左孩子指针还是右孩子指针
        if (this->m_pParent->m_pLchild == this)
        {
            this->m_pParent->m_pLchild =NULL; //如果当前节点是父节点的左孩子,则置空父节点的
        }
        if (this->m_pParent->m_pRchild == this)
        {
            this->m_pParent->m_pRchild =NULL;
        }
    }
    delete this; 
       //这里没有显示的定义析构函数的原因是,删除节点的时候,该节点的所有指针对象都已经是空值了,没有释放内存空间的需要
      // 自身节点也就是一个数据域,使用系统默认的析构函数就能完成这一点
       //最后再删除本身这个节点,递归执行到这一步,就是叶子节点做的操作,这一层递归结束后,它的父节点就变成了叶子节点,递归很合理
}
template<typename T>
void Tree_Node<T>::Preorder()  // 二叉树的前序遍历
{
    //前序遍历先输出本身,再输出左子树,后输出右子树,递归的使用本身
    cout<<this->m_iIndex<<":"<<this->m_TData<<endl;
    if (this->m_pLchild !=NULL) //如果当前的左节点不为空,则递归输出左节点以及左节点的后代
    {
        this->m_pLchild->Preorder();
    }
    if (this->m_pRchild !=NULL) 
    {
        this->m_pRchild->Preorder();
    }
}
template<typename T>
void Tree_Node<T>::Inorder() //二叉树的中序遍历
{

    //中序遍历先输出左子树,再输出根,后输出右子树
    if (this->m_pLchild !=NULL) //如果当前的左节点不为空,则递归输出左节点以及左节点的后代
    {
        this->m_pLchild->Inorder();
    }
    cout<<this->m_iIndex<<":"<<this->m_TData<<endl;
    if (this->m_pRchild !=NULL)
    {
        this->m_pRchild->Inorder();
    }
}
template<typename T>
void Tree_Node<T>::Postorder() //二叉树的后序遍历
{
    if (this->m_pLchild !=NULL) //如果当前的左节点不为空,则递归输出左节点以及左节点的后代
    {
        this->m_pLchild->Postorder();
    }
    if (this->m_pRchild !=NULL)
    {
        this->m_pRchild->Postorder();
    }
    cout<<this->m_iIndex<<":"<<this->m_TData<<endl; // 最后输出根节点的信息
}
#endif
------------------------------二叉树类的实现,带有模板参数的类,声明和实现最好放在一个文件中,不容易出错
#ifndef TREE_h
#define TREE_h
#include "Tree_Node.h"
template<typename T>
class Tree
{
public:
    Tree();
    Tree_Node<T>* searchNode(int _index); //从根节点递归的方法向下搜索树,知道找到节点的索引等于参数的索引值
    bool AddNode(int _index, int _direction,Tree_Node<T>* pNode); //添加节点
    bool DeleteNode(int _index); //删除节点,不仅仅要删除自己,还要删除自己所有的后代节点,父节点的指向,用递归来实现
    ~Tree(); //析构函数
    //树的前序遍历,后序遍历和中序遍历都是递归的方法,递归的调用节点中的方法,从这里就看到面向对象编程的好处了,比C语言的方法简单多了
    void Preorder();
    void Inorder();
    void Postorder();
private:
    Tree_Node<T>* m_pTree;
};
template<typename T>
Tree<T>::Tree()
{
    this->m_pTree = new Tree_Node<T>();
    //第一个节点为根节点,索引默认为0,未指定它的孩子节点,所以孩子节点指针为空,父节点不存在,指向默认为空
    //这个地方出现了错误,写代码的时候语法没有检测出来,任何地方使用带有模板参数的函数都要加上参数列表
    //错误的写法:this->m_pTree = new Tree_Node();
}
template<typename T>
Tree_Node<T>* Tree<T>::searchNode(int _index)
{
    return this->m_pTree->searchNode(_index);
}
template<typename T>
bool Tree<T>::AddNode(int _index, int _direction,Tree_Node<T>* pNode)
{
    Tree_Node<T>* direction_node = this->searchNode(_index); 
                          //插入节点是在指定的节点下插入,如果这个指定的节点不存在,插入操作就失败了
    if (direction_node ==NULL)
    {
        return false;
    }
    //不能传进来的临时节点pNode做为树中新增的结点,因为是对指针的操作,外部操作pNode会同步影响到插入树中节点的值,应该重新申请一块内存空间
    Tree_Node<T>* new_node =new Tree_Node<T>();
    if (NULL == new_node)
    {
        return false;
    }
    new_node->m_iIndex = pNode->m_iIndex;
    new_node->m_TData= pNode->m_TData;
    //新增节点的父节点
    new_node->m_pParent = direction_node;
    if (_direction ==0) //如果插入的是左孩子,指针指向如下
    {
        direction_node->m_pLchild = new_node;
        // 程序这里默认,目标节点没有孩子节点,二叉树的构造是从上到下一步一步构造的
       //实际上有了删除节点的方法,即使该节点有过孩子节点,只需删除该孩子节点,也不是很麻烦
    }
    if (_direction ==1) //如果是右孩子,则当前节点指向目标节点
    {
        direction_node->m_pRchild = new_node;
    }
    return true;
}
template<typename T>
bool Tree<T>::DeleteNode(int _index) // 删除节点,这一步应该放在
{
    Tree_Node<T>* direction_node = this->searchNode(_index);
    if (NULL == direction_node) //如果目标节点为空,那么删除操作也就没有意义了
    {
        return false;
    }
    //如果不为空则调用节点对象的删除方法
    direction_node->DeleteNode();
    return true;
}
template<typename T>
Tree<T>::~Tree()
{
    //树的析构函数执行起来就很简单了,直接对根节点调用deleteNode函数就可以了
    this->m_pTree->DeleteNode();
    // 或者 DeleteNode(0)
}
template<typename T>
void Tree<T>::Preorder()
{
    //前序遍历
    this->m_pTree->Preorder();
}
template<typename T>
void Tree<T>::Inorder()
{
    //中序遍历
    this->m_pTree->Inorder();
}
template<typename T>
void Tree<T>::Postorder()
{
    //后续遍历
    this->m_pTree->Postorder();
}
#endif
--------------------测试主文件
#include <iostream>
#include <stdlib.h>
#include "Tree.h"
using namespace std;

int main()
{
    Tree<int>* tree =new Tree<int>();
    //生成一个树的,默认有一个根节点,根节点不放数据,索引默认为0
    Tree_Node<int>* node1 = new Tree_Node<int>();
    node1->m_iIndex =1;
    node1->m_TData  =9;
    Tree_Node<int>* node2 = new Tree_Node<int>();
    node2->m_iIndex =2;
    node2->m_TData  =8;
    //在根节点下插入1和2号子节点
    tree->AddNode(0,0,node1);
    tree->AddNode(0,1,node2);
    Tree_Node<int>* node3 = new Tree_Node<int>();
    node3->m_iIndex =3;
    node3->m_TData  =7;
    Tree_Node<int>* node4 = new Tree_Node<int>();
    node4->m_iIndex =4;
    node4->m_TData  =6;
    //在1号节点下插入3和4号子节点
    tree->AddNode(1,0,node3);
    tree->AddNode(1,1,node4);
    Tree_Node<int>* node5 = new Tree_Node<int>();
    node5->m_iIndex =5;
    node5->m_TData  =5;
    Tree_Node<int>* node6 = new Tree_Node<int>();
    node6->m_iIndex =6;
    node6->m_TData  =4;
    //在2号节点下插入5和6号子节点
    tree->AddNode(2,0,node5);
    tree->AddNode(2,1,node6);
    //前序遍历:0 1 3 4 2 5 6
    tree->Preorder();
    cout<<"---------------------"<<endl;
    //中序遍历:3 1 4 0 5 2 6
    tree->Inorder();
    cout<<"---------------------"<<endl;
    //后序遍历:3 4 1 5 2 6 0
    tree->Postorder();
    cout<<"---------------------"<<endl;
    cout<<*(tree->searchNode(3))<<endl; //返回3:7 模板类的输出运算符友元函数形式重载成功,特例,一定要记住,会用
    cout<<"---------------------"<<endl;

   // 删除操作的实现
    tree->DeleteNode(2);
    tree->Preorder();
    system("pause");
    return 0;
}
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
防冻液对树木的产生什么后果
找歌you had me at hello谁有A DAY TO REMEMB
中盐甘肃省盐业集团积石山县盐业有限责任公司
在恐怖庄园的秘密里要怎么样旋转木雕才能拿到
伊香饼屋怎么去啊,有知道地址的么
有一种感情,既惦记,又悲愤,又恨,那是什么
在证券投资顾问业务中,证券公司、证券投资咨
过的笔顺笔画顺序
田园小吃在什么地方啊,我要过去处理事情
dona's减肥药一瓶多少钱
【o牌车】汽车牌号上的0与O有区别吗?
田田圈农业服务中心迎宾农资店地址有知道的么
我的转转交易查不到
地脚螺栓模板如何套定额
下列有关光合作用的叙述,正确的是BA. 光反应
推荐资讯
李菲的唐康藏茶咋样?有什么特别的效果吗?
南京MF47万用表电阻档的俢理
在资本充足性管理中,资产回报率(ROA)是一
瓷禧我想知道这个在什么地方
煮牛肉时如何除腥味?
北京利达消防主机怎么打印
气谱上的铂电阻在哪里
围棋和五子棋一样吗
连云港吉鑫化工有限公司这个地址在什么地方,
蒸馒头用的布 叫什么
青阳县水务局系统工会在什么地方啊,我要过去
能不能再帮我用韩语翻译一下下面的文字?谢谢
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?