线索化二叉树

二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只 能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继。
为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。
这里写图片描述

前序的线索化:也是建立在前序的递归遍历的基础之上的

    void _PreThread(Node*cur, Node*&prev)
    {
        if (cur == NULL)
        {
            return;
        }
        if (cur->Lchild == NULL)
        {
            cur->Lchild = prev;
            cur->LeftTag = THREAD;
        }
        if (prev&&prev->Rchild == NULL)
        {
            prev->Rchild = cur;
            prev->RightTag = THREAD;
        }   
        prev = cur;
        if (cur->LeftTag == LINK)
        {
            _PreThread(cur->Lchild,prev);
        }
        if (cur->RightTag == LINK)
        {
            _PreThread(cur->Rchild,prev);
        }
    }

根据前序的线索化我们可以写出非递归也不用借助栈就可以实现前序的遍历操作

void PrevOrderThread()
    {
        Node*cur = _root;
        while (cur->LeftTag == LINK)
        {
            cout << cur->data << " ";
            cur = cur->Lchild;
        }
        cout << cur->data << " ";
        cur = cur->Rchild;
    }

中序线索化:中序的线索化实际上是建立在中序的递归遍历的基础之上

    void _InThread(Node*root, Node* &prev)
    {
        if (root)
        {
            _InThread(root->Lchild, prev);
            if (root->Lchild == NULL)
                root->Lchild = prev;
            {
                root->LeftTag = THREAD;
            }
            if (prev!=NULL&&prev->Rchild == NULL)
            {
                prev->Rchild = root;
                prev->RightTag = THREAD;
            }
            prev = root;
            _InThread(root->Rchild,prev);
        }
    }

根据中序的线索化我们可以写出非递归也不用借助栈就可以实现中序的遍历操作

void InOrderThread(Node *root)
    {
        if (root == NULL)
        {
            return;
        }
        Node *cur = root;
        while (cur!=NULL)
        {
            while (cur->LeftTag == LINK)
            {
                cur = cur->Lchild;
            }
            cout << cur->data<<" ";
            while (cur->RightTag == THREAD)
            {
                cur = cur->Rchild;
                if (cur == NULL)
                {
                    return;
                }
                cout << cur->data<<" ";
            }
                cur = cur->Rchild;
            }
        }

二叉树的后序线索化需要使用三叉链

#include<iostream>
#include<stdlib.h>
using namespace std;
enum 
{
    LINK,
    THREAD
};
template<class T>
struct BinaryTreeNode
{
    BinaryTreeNode(const T&x)
    :left(NULL)
    ,right(NULL)
    , parent(NULL)
    , data(x)
    , LeftTag(LINK)
    , RightTag(LINK)
    {

    }
    BinaryTreeNode<T>*left;
    BinaryTreeNode<T>*right;
    BinaryTreeNode<T>*parent;
    size_t LeftTag;
    size_t RightTag;
    T data;
};
template<class T>
class BinaryTree
{
    typedef BinaryTreeNode<T> Node;
public:
    BinaryTree()
    {
        _root = NULL;//空树
    }
    BinaryTree(T*arr, size_t size, size_t invalid)
    {
        size_t index = 0;
        Node*prev = NULL;
        _root = _CreateBinaryTree(arr, size, invalid, index,prev);
    }
    void PostThread()
    {
        Node*prev = NULL;
        Node*par = NULL;
        _PostThread(_root, prev);
    }
 void PostOrder()          //后序遍历  后序线索化二叉树
       {
              if (_root == NULL)
                     return;
              Node* cur = _root;
              while (cur->LeftTag == LINK || cur->RightTag == LINK) 
              {
                  if (cur->LeftTag == LINK)
                           cur = cur->left;
                     else if (cur->RightTag == LINK)
                           cur = cur->right;
              }
              cout << cur->data << " ";
              Node* p = NULL;
              while ((p = cur->parent) != NULL)
              {
                     if (p->right == cur || p->RightTag == THREAD)
                           cur = p;
                     else
                     {
                           cur = p->right;
                           while (cur->LeftTag == LINK || cur->RightTag == LINK)
                           {
                                  if (cur->LeftTag == LINK)
                                         cur = cur->left;
                                  else if (cur->RightTag == LINK)
                                         cur = cur->right;
                           }
                     }
                     cout << cur->data << " ";
              }
              cout << endl;
       }

protected:
    Node*_CreateBinaryTree(T*arr, size_t size, size_t invalid, size_t &index,Node*&prev)
    {
        Node*root = NULL;
        if (index < size&&arr[index] != invalid)
        {
            root = new Node(arr[index]);
            root->parent = prev;
            prev = root;
            root->left = _CreateBinaryTree(arr, size, invalid, ++index,prev);
            prev = root;
            root->right = _CreateBinaryTree(arr, size, invalid,++index,prev);
        }
        return root;
    }
    void _PostThread(Node*cur,Node*&prev)
    {

        if (cur == NULL)
        {
            return;
        }
            _PostThread(cur->left, prev);
            _PostThread(cur->right, prev);
            if (cur->left == NULL)
            {
                cur->left = prev;
                cur->LeftTag = THREAD;
            }
                if (prev&&prev->right == NULL)
                {
                    prev->right = cur;
                    prev->RightTag = THREAD;
                }
                prev = cur;
        }
    Node* _root;
};
void PostFunTest()
{
    int arr[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
    BinaryTree<int> t1(arr, (sizeof(arr) / sizeof(arr[0])), '#');
    BinaryTree<int> t2(array, (sizeof(array) / sizeof(array[0])), '#');
    t1.PostThread();
    t1.PostOrder();
    cout << endl;
    t2.PostThread();
    t2.PostOrder();
}
int main()
{
    PostFunTest();
    system("pause");
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值