线索化二叉树

中序线索化(递归):

图形解析:

这里写图片描述

代码如下:

//中序线索化
    void InorderThreading()
    {
       Node* prev = NULL;
       _InoderThreading(_root, prev);
    }

void _InoderThreading(Node* cur, Node* & prev)
    {
       if (cur)
       {
           _InoderThreading(cur->_left, prev);
           if (NULL == cur->_left)//当前节点的左节点需要线索化
           {
               cur->_left = prev;
               cur->_leftType = THREAD;
           }
           if (prev && NULL == prev->_right)//当前节点的前驱的右节点需要线索化
           {
               prev->_right = cur;
               prev->_rightType = THREAD;
           }
           prev = cur;//更新prev
           _InoderThreading(cur->_right, prev);
       }
    }

中序遍历中序线索化:

这里写图片描述

代码如下:


    //中序遍历
    void InOrder()
    {
       _InOrder(_root);
       cout << endl;
    }

//中序线索二叉树的中序遍历算法
    void InorderThd()
    {
       Node* cur = _root;
       while (cur)
       {
           //查找最左节点
           while (cur->_leftType == LINK)
           {
               cur = cur->_left;
           }
           cout << cur->_data << " ";
           //方法1
           while (cur->_rightType == THREAD)
           {
               cur = cur->_right;
               if (NULL == cur)
               {
                  return;
               }
               cout << cur->_data << " ";
           }
           //执行到此处-->说明右节点为右子树
           cur = cur->_right;
       }
    }

前序线索化二叉树:

void _PreOrderThreading(Node* cur,Node*& prev)
    {
       if (NULL == cur)
       {
           return;
       }
       if (NULL == cur->_left)
       {
           cur->_left = prev;
           cur->_leftType = THREAD;
       }
       if (prev && NULL == prev->_right)
       {
           prev->_right = cur;
           prev->_rightType = THREAD;
       }
       prev = cur;//更新prev的值

       if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
       {
           _PreOrderThreading(cur->_left, prev);
       }
       if (cur->_rightType == LINK)
       {
           _PreOrderThreading(cur->_right, prev);
       }
    }

前序遍历前序线索化二叉树:

前序线索化二叉树的前序遍历算法(下面的代码很坑、有问题):

//前序遍历二叉树
    void PreOrderThd()
    {
       Node* cur = _root;
       while (cur)
       {
           //访问左子树
           while (cur->_leftType == LINK)
           {
               cout << cur->_data << " ";
               cur = cur->_left;
           }
           //此时的cur->_leftType == THREAD
           cout << cur->_data << " ";

           //1.子问题  2.cur->_rightType = THREAD
           while (cur->_rightType == THREAD)
           {
               cur = cur->_right;
               cout << cur->_data << " ";
           }
           cur = cur->_right;//子问题
       }
    }

测试代码1如下:

int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    BinaryTreeThd<int> bt1(array1, sizeof(array1) / sizeof(int), '#');
    bt1.PreOrder();
    bt1.PreOrderThreading();
    bt1.PreOrderThd();

结果如下:

这里写图片描述

测试代码2如下:

  int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
    BinaryTreeThd<int> bt(array, sizeof(array) / sizeof(int), '#');
    bt.PreOrder();
    bt.PreOrderThreading();
    bt.PreOrderThd();

这里写图片描述

很明显,结果不对,下面我们来仔细分析其中存在的问题:

这里写图片描述

将上面的程序改之:

//前序遍历二叉树
    void PreOrderThd()
    {
       Node* cur = _root;
       while (cur)
       {
           //访问左子树
           while (cur->_leftType == LINK)
           {
               cout << cur->_data << " ";
               cur = cur->_left;
           }
           //此时的cur->_leftType == THREAD
           cout << cur->_data << " ";

           cur = cur->_right;
       }
    }

测试代码如下:

void TestBinary()
{
    int array1[10] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    BinaryTreeThd<int> bt1(array1, sizeof(array1) / sizeof(int), '#');
    bt1.PreOrder();
    bt1.PreOrderThreading();
    bt1.PreOrderThd();
    cout << endl;
    int array[15] = { 1, 2, '#', 3, '#', '#', 4, 5, '#', 6, '#', 7, '#', '#', 8 };
    BinaryTreeThd<int> bt(array, sizeof(array) / sizeof(int), '#');
    bt.PreOrder();
    bt.PreOrderThreading();
    bt.PreOrderThd();
}

结果如下:

这里写图片描述

代码如下:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include <assert.h>
using namespace std;

enum PointerType
{
    LINK,
    THREAD,
};

template<class T>
struct BinaryTreeThdNode
{
    BinaryTreeThdNode(const T& value)
    :_data(value)
    , _left(NULL)
    , _right(NULL)
    , _leftType(LINK)
    , _rightType(LINK)
    {}

    T _data;
    BinaryTreeThdNode<T>* _left;
    BinaryTreeThdNode<T>* _right;

    PointerType _leftType;//标记是否需要线索化
    PointerType _rightType;
};

template<class T>
class BinaryTreeThd
{
    typedef BinaryTreeThdNode<T> Node;
public:
    BinaryTreeThd(const Node* node)
       :_root(node)
    {}
    BinaryTreeThd(const T* arr, size_t size, const T& invalid)
    {
       size_t index = 0;
       _root = _CreatTree(arr, size, invalid, index);
    }

    //先序遍历
    void PreOrder()
    {
       _PreOrder(_root);
       cout << endl;
    }

    //中序遍历
    void InOrder()
    {
       _InOrder(_root);
       cout << endl;
    }
    //后序遍历
    void PostOrder()
    {
       _PostOrder(_root);
       cout << endl;
    }

    //中序线索化
    void InorderThreading()
    {
       Node* prev = NULL;
       _InoderThreading(_root, prev);
    }
//中序线索二叉树的中序遍历算法
    void InorderThd()
    {
       Node* cur = _root;
       while (cur)
       {
           //查找最左节点
           while (cur->_leftType == LINK)
           {
               cur = cur->_left;
           }
           cout << cur->_data << " ";
           //方法1
           while (cur->_rightType == THREAD)
           {
               cur = cur->_right;
               if (NULL == cur)
               {
                  return;
               }
               cout << cur->_data << " ";
           }
           //执行到此处-->说明右节点为右子树
           cur = cur->_right;
       }
    }

    //前序线索二叉树的前序遍历算法
    void PreOrderThreading()
    {
       Node* prev = NULL;
       _PreOrderThreading(_root, prev);
       if (NULL == prev)
       {
           prev->_rightType = THREAD;
       }
    }

    void PreOrderThd()
    {
       if (NULL == _root)
       {
           return;
       }

       Node* cur = _root;
       while (cur)
       {
           //访问根节点
           cout << cur->_data << " ";
           //访问左子树
           while (cur->_leftType == LINK)
           {
               cur = cur->_left;
               cout << cur->_data << " ";
           }
           //此时的cur->_leftType == THREAD

           while (cur->_rightType == THREAD)
           {
               cur = cur->_right;
               cout << cur->_data << " ";
           }
           cur = cur->_right;//子问题
       }
    }

    //后序线索化二叉树
    void PostOrderThreading()
    {
       Node* prev = NULL;
       _PostOrderThreading(_root,prev);
    }

    //后序遍历
    void PostOrderThd()
    {
       if (NULL == _root)
       {
           return;
       }
       Node* cur = NULL;
       while (cur)
       {
           while (LINK == cur->_leftType || Link == cur->_rightType)
           {
               if (LINK == cur->_leftType)
               {
                  cur = cur->_left;
               }
               if (LINK == cur->_rightType)
               {
                  cur = cur->_right;
               }
           }
           cout << cur->_data << " ";

           Node* p = NULL;

       }

    }

protected:
    //左、右、根
    void _PostOrderThreading(Node* cur,Node*& prev)
    {
       if (NULL == cur)
       {
           return;
       }
           _PostOrderThreading(cur->_left, prev);
           _PostOrderThreading(cur->_right, prev);
       if (NULL == cur->_left)
       {
           cur->_left = prev;
           cur->_leftType = THREAD;
       }
       if (prev && NULL == prev->_right)
       {
           prev->_right = cur;
           prev->_rightType = THREAD;
       }
       prev = cur;//更新prev的值
    }

    void _PreOrderThreading(Node* cur,Node*& prev)
    {
       if (NULL == cur)
       {
           return;
       }
       if (NULL == cur->_left)
       {
           cur->_left = prev;
           cur->_leftType = THREAD;
       }
       if (prev && NULL == prev->_right)
       {
           prev->_right = cur;
           prev->_rightType = THREAD;
       }
       prev = cur;//更新prev的值

       if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
       {
           _PreOrderThreading(cur->_left, prev);
       }
       if (cur->_rightType == LINK)
       {
           _PreOrderThreading(cur->_right, prev);
       }
    }

    void _PreOrder(Node* root)
    {
       if (root)
       {
           cout << root->_data << " ";
           _PreOrder(root->_left);
           _PreOrder(root->_right);
       }
    }

    void _InOrder(Node* root)
    {
       if (root)
       {
           _InOrder(root->_left);
           cout << root->_data << " ";
           _InOrder(root->_right);
       }
    }

    void _PostOrder(Node* root)
    {
       if (root)
       {
           _PostOrder(root->_left);
           _PostOrder(root->_right);
           cout << root->_data << " ";
       }
    }

    void _InoderThreading(Node* cur, Node* & prev)
    {
       if (cur)
       {
           _InoderThreading(cur->_left, prev);
           if (NULL == cur->_left)//当前节点的左节点需要线索化
           {
               cur->_left = prev;
               cur->_leftType = THREAD;
           }
           if (prev && NULL == prev->_right)//当前节点的前驱的右节点需要线索化
           {
               prev->_right = cur;
               prev->_rightType = THREAD;
           }
           prev = cur;//更新prev
           _InoderThreading(cur->_right, prev);
       }
    }

    Node* _CreatTree(const T* arr, size_t size, const T& invalid, size_t& index)
    {
       Node* newRoot = _root;
       if (index < size && arr[index] != invalid)
       {
           newRoot = new Node(arr[index]);
           newRoot->_left = _CreatTree(arr, size, invalid, ++index);
           newRoot->_right = _CreatTree(arr, size, invalid, ++index);
       }
       return newRoot;
    }

private:
    Node* _root;
};

前序线索化二叉树:

void _PreOrderThreading(Node* cur,Node*& prev)
    {
       if (NULL == cur)
       {
           return;
       }
       if (NULL == cur->_left)
       {
           cur->_left = prev;
           cur->_leftType = THREAD;
       }
       if (prev && NULL == prev->_right)
       {
           prev->_right = cur;
           prev->_rightType = THREAD;
       }
       prev = cur;//更新prev的值

       if (cur->_leftType == LINK)//因为是先线索化后进行递归,为了避免死循环,所以需要判断
       {
           _PreOrderThreading(cur->_left, prev);
       }
       if (cur->_rightType == LINK)
       {
           _PreOrderThreading(cur->_right, prev);
       }
    }


中序线索化二叉树的迭代器:

template<class T>
struct BinaryTreeThdIterator
{
    typedef BinaryTreeThdNode<T> Node;
    typedef BinaryTreeThdIterator<T> self;

    BinaryTreeThdIterator(Node* node)
       :_node(node)
    {}

    T& operator*()
    {
       return _node->_data;
    }

    T* operator->()
    {
       return &(_node->_data);
    }

    self& operator++()
    {
       //后继
       if (_node->_rightType == THREAD)
       {
           _node = _node->_right;
       }
       else//子问题
       {
           Node* cur = _node->_right;
           while (cur->_leftType == LINK)
           {
               cur = cur->_left;
           }
           _node = cur;
       }
       return *this;
    }

    bool operator!=(const self& cur)const
    {
       return _node != cur._node;
    }

    bool operator==(const self& cur)const
    {
       return _node == cur._node;
    }

    Node* _node;
};

总结:
本文概要:1.中序线索化二叉树
2.中序遍历中序线索化二叉树
3.前序线索化二叉树
4.前序遍历前序线索化二叉树(易入坑)
5.中序线索化二叉树的迭代器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值