二叉树的线索化

 一、线索二叉树的引入

 二叉树是一种非线性结构,遍历二叉树几乎都是通过递归或者用栈辅助实现非递归的遍历。用二叉树作为存储结构时,取到一个节点,只能获取节点的左孩子和右孩子,不能直接得到节点的任一遍历序列的前驱或者后继

 为了保存这种在遍历中需要的信息,我们利用二叉树中指向左右子树的空指针来存放节点的前驱和后继信息。

二、线索二叉树的构造

线索二叉树的节点结构:

线索二叉树的节点定义:  

enum PointTag
{
	LINK,//子树
	THREAD,//线索
};
template <class T>
struct BinaryTreeThdNode
{
	T _data;//节点数据
	BinaryTreeThdNode<T>* _left;//当前节点的左孩子
	BinaryTreeThdNode<T>* _right;//当前节点的右孩子
 
	PointTag _leftTag;//当前节点的左孩子线索标志
	PointTag _rightTag;//当前节点的右孩子线索标志
};

 

  当_leftTag == LINK,则表示_left为指向节点的左孩子,_leftTag == THEAD,则表示_left为线索,指向节点的直接前驱。

        当_rightTag == LINK,则表示_right为指向节点的右孩子,_rightTag == THEAD,则表示_right为线索,指向节点的直接后继。
 

三、代码实现二叉树的线索化

线索化二叉树可分为前序线索二叉树、中序线索二叉树、后序线索二叉树

代码实现:

#include <iostream>
using namespace std;

enum PointTag
{
    LINK,
    THREAD,
};

template <typename T>
struct BinaryTreeThdNode
{
    typedef BinaryTreeThdNode<T> Node;
    T _data;
    Node *_left;
    Node *_right;
    Node *_parent;
    PointTag _leftTag;
    PointTag _rightTag;
    BinaryTreeThdNode(const T &x)
        : _data(x), _left(NULL), _right(NULL), _parent(NULL), _leftTag(LINK), _rightTag(LINK)
    {
    }
};

template <typename T>
class BinaryTreeThd
{
public:
    typedef BinaryTreeThdNode<T> Node;

public:
    BinaryTreeThd()
        : _node(NULL)
    {
    }
    BinaryTreeThd(T *arr, size_t size, const T &invalid)
    {
        int index = 0;
        Node *parent = NULL;
        _node = _CreateBinaryTreeThd(arr, size, index, invalid, parent); //构造二叉树
    }
    void PreOrderThd() //前序线索化
    {
        Node *pre = NULL;
        _preOrderTheraing(_node, pre);
    }
    //先序线索花后的前序遍历
    void Preorder()
    {
        // Node *root = _node;
        _PreOrder(_node);
    }
    void InOrderThread() //中序遍历的线索化
    {
        Node *prev = NULL;
        _InOrderThreading(_node, prev);
    }
    //中序线索化的中序遍历
    void Inoeder()
    {
        _InOrder();
    }
    void PostOrderThead() //后序遍历的线索化
    {
        Node *prev = NULL;
        _PostOrderTheading(_node,prev);
    }
    void PostOrder()
    {
        _PostOrder();
    }

protected:
    Node *_CreateBinaryTreeThd(T *arr, size_t size, int &index, const T &invalid, Node *&parent)
    {
        Node *root = NULL;
        if (arr[index] != invalid && index < size)
        {
            root = new Node(arr[index]);
            root->_parent = parent;
            root->_left = _CreateBinaryTreeThd(arr, size, ++index, invalid, root);
            root->_right = _CreateBinaryTreeThd(arr, size, ++index, invalid, root);
        }
        return root;
    }
    void _preOrderTheraing(Node *cur, Node *&pre)
    {
        if (cur == NULL)
        {
            return;
        }
        if (cur->_left == NULL)
        {
            cur->_left = pre;
            cur->_leftTag = THREAD;
        }
        if (pre && pre->_right == NULL)
        {
            pre->_rightTag = THREAD;
            pre->_right = cur;
        }
        pre = cur;
        if (cur->_leftTag == LINK)
        {
            _preOrderTheraing(cur->_left, pre);
        }
        if (cur->_rightTag == LINK)
        {
            _preOrderTheraing(cur->_right, pre);
        }
    }
    void _PreOrder(Node *root)
    {
        Node *cur = root;
        while (cur)
        {
            while (cur->_leftTag == LINK)
            {
                cout << cur->_data << " ";
                cur = cur->_left;
            }
            cout << cur->_data << " ";
            cur = cur->_right;
        }
    }
    void _InOrderThreading(Node *_node, Node *&pre)
    {
        Node *cur = _node;
        {
            if (cur == NULL)
            {
                return;
            }
            if (cur->_leftTag == LINK)
            {
                _InOrderThreading(cur->_left, pre);
            }
            if (cur->_left == NULL)
            {
                cur->_left = pre;
                cur->_leftTag = THREAD;
            }
            if (pre && pre->_right == NULL)
            {
                pre->_rightTag = THREAD;
                pre->_right = cur;
            }
            pre = cur;
            if (cur->_rightTag == LINK)
            {
                _InOrderThreading(cur->_right, pre);
            }
        }
    }
    void _InOrder()
    {
        Node *cur = _node;
        if (cur == NULL)
        {
            return;
        }
        while (cur)
        {
            while (cur->_leftTag == LINK)
            {
                cur = cur->_left;
            }
            cout << cur->_data << " ";
            while (cur->_rightTag == THREAD)
            {
                cur = cur->_right;
                cout << cur->_data << " ";
            }
            cur = cur->_right;
        }
    }
    void _PostOrderTheading(Node *_node, Node *&pre)
    {
        Node *cur = _node;
        {
            if (cur == NULL)
            {
                return;
            }
            if (cur->_leftTag == LINK)
            {
                _PostOrderTheading(cur->_left, pre);
            }
            if (cur->_rightTag == LINK)
            {
                _PostOrderTheading(cur->_right, pre);
            }
            if (cur->_left == NULL)
            {
                cur->_left = pre;
                cur->_leftTag = THREAD;
            }
            if (pre && pre->_right == NULL)
            {
                pre->_rightTag = THREAD;
                pre->_right = cur;
            }
            pre = cur;
        }
    }
    void _PostOrder()
    {
        Node *cur = _node;
        Node *prev = NULL;
        while (cur)
        {
            //寻找最左节点
            while (cur->_left != prev && cur->_leftTag == LINK)
            {
                cur = cur->_left;
            } //cur==_node或NULL结束循环

            //访问后继
            while (cur && cur->_rightTag == THREAD) //当前节点的右指针为线索
            {
                cout << cur->_data << " ";
                prev = cur;
                cur = cur->_right;
            }

            if (cur == _node) //判断节点是否指向了根节点
            {
                cout << cur->_data << endl;
                return;
            }

            while (cur && cur->_right == prev)
            {
                cout << cur->_data << " ";
                prev = cur;
                cur = cur->_parent; //向上一层走
            }
            if (cur && cur->_rightTag == LINK) //cur->_rightTag == LINK(当前节点的右指针为子树)
            {
                cur = cur->_right;
            }
        }
    }

private:
    Node *_node;
};

void testBinarTreeThd()
{
    int array[10] = {1, 2, 3, '#', '#', 4, '#', '#', 5, 6};
    size_t size = sizeof(array) / sizeof(array[0]);
    BinaryTreeThd<int> bt(array, size, '#');
    // bt.PreOrderThd();
    // bt.Preorder();
    // bt.InOrderThread();
    // bt.Inoeder();
    bt.PostOrderThead();
    bt.PostOrder();
}
int main()
{
    testBinarTreeThd();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值