设计并实现基于后序线索二叉树的后序遍历的非递归算法。(c++)

设计并实现基于后序线索二叉树的后序遍历的非递归算法。

一、二叉树的创建
我们使用二叉链表得方式进行二叉树存数。每个结构有一个数据域,存放结点的数据,还有两个左右指针,以及两个标志。当标志为0时表示指向孩子,标志为1时,指向线索。
二叉树的创建根据扩展线序序列创建的。当左右孩子为空时,以“.”来代替。

代码如下:

template<class T>//创建二叉树
void xstree<T>::create(tbnode<T>*& t) {
    T x;
    cin >> x;
    if (x == '.')
        t = NULL;
    else
    {
        t = new tbnode<T>;
        t->data = x;
        create(t->lchild);
        create(t->rchild);
        root = t;
    }
}

二、后序的递归思想。
这个比较简单,就是根据后序的定义,左右根来对二叉树进行遍历的,主要就是递归。

template<class T>
void xstree<T>::post_order(tbnode<T>* t)         //后序遍历
{
    if (t != NULL)
    {
        post_order(t->lchild);
        post_order(t->rchild);
        cout << t->data <<" ";
    }
}

三、后序的非递归思想。
非递归实现我们需要使用到栈这样的数据结构。我使用的是c++STL中的栈。
1.首先我们需要做的是二叉树的后序线索化。
(1)如果在当前指针指向的节点为空,则返回。
(2)依次后序线索化左子树,后序线索化右子树
(3)如果当前节点的左孩子为空,那么当前节点的ltag=1;且lchild指针指向其前驱。
(4)如果当前节点的前驱节点不为空,且前驱的右孩子为空,则前驱的rtag=1,且后继即为当前节点。
(5)前驱节点等于当前节点。

按着上述步骤即可完成二叉树的后序线索化。

template<class T>//二叉树的线索化
void xstree<T>::postthread(tbnode<T>* &t)
{
    if (t == NULL)
        return;
    postthread(t->lchild);
    postthread(t->rchild);
    if (t->lchild == NULL)//当前节点前驱
    {
        t->ltag = 1;
        t->lchild = pre;
    }
    if (pre != NULL && pre->rchild == NULL)//前驱节点后继
    {
        pre->rtag = 1;
        pre->rchild = t;
    }
    pre = t;//指针传递
}

2.后序线索二叉树中,求节点的前驱。
(a) 若p有右孩子 —— 右孩子结点是其前驱;
(b) 否则,若
P有左孩子 —— 左孩子结点是其前驱;
(c)否则 —— p -> lchild是其前驱线索 。

template<class T>
tbnode<T>* xstree<T>::postpre(tbnode<T>* p){
    if (p->rtag == 0) return (p->rchild);
    else return (p->lchild);
}

3.然后我们就需要建立一个栈,并且从根节点开始,求其前驱,并将前驱入栈。求完之后。再将他们依次出栈即可。

四、实验数据
所使用的二叉树
在这里插入图片描述

结果如下:
在这里插入图片描述
在这里插入图片描述

五、源代码:

//源代码如下
#include<iostream>
#include<stack>
using namespace std;

template<class T>
struct  tbnode {
    T  data;
    tbnode* lchild=NULL, * rchild=NULL;
    bool   ltag=0, rtag=0;
};

template<class T>
class xstree {
public:
    xstree();
    ~xstree();
    void create(tbnode<T>*&t);//创建普通二叉树
    void postthread(tbnode<T>* &t);//后序线索化
    tbnode<T>* postpre(tbnode<T>* p);//求后序二叉树的前驱节点
    void postorder(tbnode<T>* t);//后序遍历(非递归)
    tbnode<T>* get_root();//获得树根
    void  post_order(tbnode<T>* t);//后序遍历(递归)
    void delete_tree(tbnode<T>* t);//删除节点,用于析构

private:
    tbnode<T>* root;
    tbnode<T>* pre;
};


template<class T>//构造函数
xstree<T>::xstree() {
    root = NULL;
    pre = NULL;
}

template<class T>
void xstree<T>::post_order(tbnode<T>* t)         //后序遍历
{
    if (t != NULL)
    {
        post_order(t->lchild);
        post_order(t->rchild);
        cout << t->data <<" ";
    }
}

template<class T>//创建二叉树
void xstree<T>::create(tbnode<T>*& t) {
    T x;
    cin >> x;
    if (x == '.')
        t = NULL;
    else
    {
        t = new tbnode<T>;
        t->data = x;
        create(t->lchild);
        create(t->rchild);
        root = t;
    }
}

template<class T>//二叉树的线索化
void xstree<T>::postthread(tbnode<T>* &t)
{
    if (t == NULL)
        return;
    postthread(t->lchild);
    postthread(t->rchild);
    if (t->lchild == NULL)//当前节点前驱
    {
        t->ltag = 1;
        t->lchild = pre;
    }
    if (pre != NULL && pre->rchild == NULL)//前驱节点后继
    {
        pre->rtag = 1;
        pre->rchild = t;
    }
    pre = t;//指针传递
}



//求前驱
template<class T>
tbnode<T>* xstree<T>::postpre(tbnode<T>* p){
    if (p->rtag == 0) return (p->rchild);
    else return (p->lchild);
}

template<class T>//后序遍历(线索树)
void xstree<T>::postorder(tbnode<T> *t) {
   stack<tbnode<T>*> S;
    tbnode<T>* p = t;
    while (p != NULL)//后序序列中,根节点的前驱依次入栈
    {
        S.push(p);
        p = postpre(p);
    }
    while (!S.empty())//出栈并输出。
    {
        p = S.top();
        S.pop();
        cout << p->data << " ";
    }
}

template<class T>
void xstree<T>::delete_tree(tbnode<T>* t)
{
    tbnode<T>* p = t;
    while (p != NULL)
    {
        tbnode<T>* q = postpre(p);
        delete p;
        p = q;
    }
}

template<class T>
xstree<T>::~xstree()
{
    delete_tree(root);
}

template<class T>
tbnode<T>* xstree<T>::get_root() {
    return root;
}

int main()
{
    tbnode<char> *p;
    xstree<char> tree;
    cout << "请输入树(先序输入):";
    tree.create(p);//创建普通二叉树
    cout << "未线索化的二叉树后序遍历为:";
    tree.post_order(p);//后序遍历普通二叉树
    cout << endl;
    p = tree.get_root();//获得树根
    tree.postthread(p);//二叉树线索化
    p = tree.get_root();//获得树根
    cout << "线索化后的线索二叉树其后序遍历为(非递归):";
    tree.postorder(p);//非递归后序遍历线索二叉树
    cout << endl;
    system("pause");
    return 0;
}
  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值