数据结构 实验报告11

一、实验目的和要求

目的:熟悉后序线索二叉树并实现后序遍历

要求:

(1)创建二叉树。

(2)转换为后序线索二叉树。

(3)实现后序遍历的非递归算法。
二、实验环境

编译器:Vscode +DevC++

系统:Windows10

CPU:i5-8265U@1.60GHz
三、实验内容

(1)创建二叉树。

(2)转换为后序线索二叉树。

(3)实现后序遍历的非递归算法。
四、实验过程
4.1 任务定义和问题分析

1.创建二叉树

沿用之前使用二叉树创建模板;(若兼容后序线索二叉树的话)

或者重新创建二叉树类(后序线索二叉树需要其他辅助变量)

      2.转换成后序线索二叉树

            在转换时只需要按照后序遍历,(需要记录当前结点的前驱)逐个将空指针利用起来

      3.实现后序遍历的非递归算法

            需要经过多重循环,首先通过while找到最左结点,然后遍历后继……
4.2 数据结构的选择和概要设计

必是选择链式结构;

在创建树时,使用扩展先序序列创建;

        详细设计

第一尝试:

      首先将之前写的二叉树类扩展了,添加了rtag和ltag变量用于识别指针是否指向儿子;其次添加了一个全局结点指针变量,用于实现对前驱的记录

      接着对后序遍历进行修改

然后就是添加函数  使其能够进行对后序非递归遍历

在编写此方面代码时就出现了问题

我的第一版函数是如下操作的

      1.先找到第一个结点(最左的结点)

      2.再遍历其后继

      3.然后再找到当前结点的最左儿子

      4.重复2,3操作直到结点为空

在实际面对下面二叉树时,就出现了预想不到的事情:

进入了死循环————CDBCDB

下面展示后序线索(绿色指向前驱,红色指向后继):

不难看出再程序寻到B时对A的左子树操作就完成了,需要去操作A的右子树,然而对于非递归遍历来说,我们现在就是过了河的卒,无法回头,在执行到B时没有操作能够支持我们去操作A的右子树

故而 添加辅助空间:父亲指针;

并在创建树时,记录每个结点的父亲结点

在执行非递归后序遍历时,操作如下

    找寻到以当前结点为根的树的后序遍历的起始节点
    按次序找寻后继并输出数据
    判断是否达到根结点(是:输出数据并结束遍历;否:进行下一步)
    逐层向上返回,并输出数据,直到是从当前左子树返回为止
    去访问右孩子
    回到第一步

五、测试及结果分析
5.1 实验数据

 
5.2 结果及分析

正确实现了二叉树向后序线索树的转换

并实现了后序遍历的非递归输出
六、实验收获

熟悉了线索二叉树

 
七、参考文献

数据结构-线索二叉树(后序线索二叉树及遍历)

《大话数据结构》
八、附录(源代码)

    /*
     * @Descripttion:
     * @version:
     * @Author: Nice_try
     * @Date: 2020-05-26 09:10:57
     * @LastEditors: Nice_try
     * @LastEditTime: 2020-05-26 17:59:12
     */
     
    #include <iostream>
     
    #include<cstdio>
     
    #include<algorithm>
     
    #include<typeinfo>
     
    using namespace std;
     
    #define Link 0   //表示该节点有非空孩子节点
     
    #define Thread 1 //表示该节点有后续节点(对于右子树来说)
     
    #define MAXSIZE 100
     
     
     
    template <class T>
     
    struct BT_Thread_Node
     
    {
     
        T Data;
     
        BT_Thread_Node *Left_Child;
     
        BT_Thread_Node *Right_Child;
     
        BT_Thread_Node *Parent; //指向该节点的父母节点
     
        int Ltag;
     
        int Rtag;
     
    };
     
     
     
    template <class T>
     
    class Thread_Binary_tree
     
    {
     
    private:
     
        BT_Thread_Node<T> *Tree;
     
        BT_Thread_Node<T> *Pre_Node;
     
        BT_Thread_Node<T> *BT_Node_Stack[MAXSIZE];
     
        int Top;
     
        int Create_Thread_BTree(BT_Thread_Node<T> *&Tree, BT_Thread_Node<T> *Parent);
     
        void PostOrder_Thread_Op(BT_Thread_Node<T> *&Tree);
     
        void _PostOrder_Op(BT_Thread_Node<T> *&Tree);
     
     
     
    public:
     
        Thread_Binary_tree();
     
        ~Thread_Binary_tree();
     
        void PostOrder_Thread();
     
        void _PostOrder();
     
    };
     
     
     
    template <class T>
     
    int Thread_Binary_tree<T>::Create_Thread_BTree(BT_Thread_Node<T> *&Tree, BT_Thread_Node<T> *Parent_Node)
     
    {
     
        T Data;
     
        cin >> Data;
     
        if(Data=='#'||Data==-1)
     
            Tree = NULL;
     
        else
     
        {
     
            Tree = new BT_Thread_Node<T>;
     
            Tree->Parent = Parent_Node; //指向父母节点
     
            Tree->Data = Data;
     
            Tree->Ltag = Link;
     
            Tree->Rtag = Link;
     
            Create_Thread_BTree(Tree->Left_Child, Tree); //Tree是孩子的父母节点
     
            Create_Thread_BTree(Tree->Right_Child, Tree);
     
        }
     
        return 1;
     
    }
     
     
     
    template <class T>
     
    void Thread_Binary_tree<T>::PostOrder_Thread_Op(BT_Thread_Node<T> *&Tree)
     
    {
     
        if (Tree == NULL)
     
            return;
     
     
     
        PostOrder_Thread_Op(Tree->Left_Child);  //左
     
        PostOrder_Thread_Op(Tree->Right_Child); //右
     
     
     
        if (Tree->Left_Child == NULL) //根
     
        {
     
            Tree->Left_Child = Pre_Node;
     
            Tree->Ltag = Thread;
     
        }
     
        if (Pre_Node != NULL && Pre_Node->Right_Child == NULL)
     
        {
     
            Pre_Node->Right_Child = Tree;
     
            Pre_Node->Rtag = Thread;
     
        }
     
     
     
        Pre_Node = Tree;
     
    }
     
     
     
    template <class T>
     
    void Thread_Binary_tree<T>::_PostOrder_Op(BT_Thread_Node<T> *&Tree)
     
    {
     
        if (Tree == NULL)
     
            return;
     
     
     
        BT_Thread_Node<T> *Cur_Node = Tree;
     
        Pre_Node = NULL;
     
        while (Cur_Node != NULL)
     
        {
     
            while (Cur_Node->Left_Child != Pre_Node) //change,找到起始节点(在左树的最左边)
     
            {
     
                Cur_Node = Cur_Node->Left_Child;
     
            }
     
     
     
            while (Cur_Node != NULL && Cur_Node->Rtag == Thread) //按线索找到次树节点
     
            {
     
                BT_Node_Stack[++Top] = Cur_Node;
     
                cout << Cur_Node->Data << " ";
     
                Pre_Node = Cur_Node; //每次访问节点后,PreNode更新
     
                Cur_Node = Cur_Node->Right_Child;
     
            }
     
     
     
            if (Cur_Node == Tree) //如果当前节点为根节点,说明遍历完成
     
            {
     
                BT_Node_Stack[++Top] = Cur_Node;
     
                cout << Cur_Node->Data << " ";
     
                return;
     
            }
     
     
     
            while (Cur_Node != NULL && Cur_Node->Right_Child == Pre_Node) //当前节点的右孩子节点刚好上次遍历,说明该袖珍树只差根就遍历完成
     
            {
     
                BT_Node_Stack[++Top] = Cur_Node;
     
                cout << Cur_Node->Data << " ";
     
                Pre_Node = Cur_Node;
     
                Cur_Node = Cur_Node->Parent; //访问袖珍树后回到上一层
     
            }
     
     
     
            if (Cur_Node != NULL && Cur_Node->Rtag == Link) //回到上一层后,先访问右孩子
     
            {
     
                Cur_Node = Cur_Node->Right_Child;
     
            }
     
        }
     
    }
     
     
     
    template <class T>
     
    Thread_Binary_tree<T>::Thread_Binary_tree() : Pre_Node(NULL), Top(-1)
     
    {
     
        Create_Thread_BTree(Tree, NULL);
     
    }
     
     
     
    template <class T>
     
    Thread_Binary_tree<T>::~Thread_Binary_tree()
     
    {
     
        while (Top != -1)
     
        {
     
            delete BT_Node_Stack[Top];
     
            Top--;
     
        }
     
    }
     
     
     
    template <class T>
     
    void Thread_Binary_tree<T>::PostOrder_Thread()
     
    {
     
        PostOrder_Thread_Op(Tree);
     
    }
     
     
     
    template <class T>
     
    void Thread_Binary_tree<T>::_PostOrder()
     
    {
     
        _PostOrder_Op(Tree);
     
    }

 

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值