线索化二叉树

    线索化二叉树为我们提供了一种不需要递归和借助栈就能遍历一颗二叉树的方法,如果将二叉树写成STL的形式,那么线索化就可以为之提供迭代器,这也是线索化二叉树的最主要的用法。线索化二叉树有三种方式,前序线索化,中序线索化和后序线索化。一般只要掌握前序线索化和中序线索化就可以了。后序线索化遍历的时候要借助于三叉链表或者FindParent(寻找父亲结点的函数)。
    将一颗搜索二叉树转换成有序双向链表,借助中序线索化的思想,将当前结点的left当成链表的前驱指针,将prev的right当成双向链表的后继指针。

前序线索化:
#pragma once
enum
{
       LINK,
       THREAD,
};
template<typename T>
struct ThreadTreeNode
{
       T _data;
       ThreadTreeNode<T> *_left;
       ThreadTreeNode<T> *_right;
       int _leftTag;
       int _rightTag;
       ThreadTreeNode(const T& data)
              :_data(data)
              , _left(NULL)
              , _right(NULL)
              , _leftTag(LINK)
              , _rightTag(LINK)
       {}
};
template<typename T>
class ThreadBinaryTree
{
       typedef  ThreadTreeNode<T> Node;
public:
       ThreadBinaryTree()
              :_root(NULL)
       {}
       ThreadBinaryTree(const T* a, size_t size, const T& invalid)
       {
              size_t index = 0;
              _root = _CreatTree(a, size, index, invalid);      //构造一颗二叉树
              PrevThreadTree();                                  //前序线索化二叉树
       }
       //前序遍历 前序线索化二叉树
       void PrevOder()
       {
              if (_root == NULL)
                     return;
              Node* cur = _root;
              while (cur)
              {
                     while (cur->_leftTag == LINK)
                     {
                           cout << cur->_data << " ";
                           cur = cur->_left;
                     }
                     cout << cur->_data << " ";
                     cur = cur->_right;
              }
              cout << endl;
       }
protected:
       //前序线索化二叉树
       void PrevThreadTree()
       {
              Node* prev = NULL;
              _PrevThreadTree(_root, prev);
              prev->_rightTag = THREAD;
       }
       Node* _CreatTree(const T* a, size_t size, size_t& index, const T& invalid)
       {
              //创建一颗二叉树
              Node* root = NULL;
              if (index < size&&a[index] != invalid)
              {
                     root = new Node(a[index]);
                     root->_left = _CreatTree(a, size, ++index, invalid);
                     root->_right = _CreatTree(a, size, ++index, invalid);
              }
              return root;
       }
       //前序 线索化二叉树
       void _PrevThreadTree(Node* root, Node* &prev)
       {
              if (root == NULL)
                     return;
              if (root->_left != NULL)
              {
                     if (prev&&prev->_right == NULL)
                     {
                           prev->_right = root;
                           prev->_rightTag = THREAD;
                     }
                     prev = root;
              }
              else
              {
                     root->_leftTag = THREAD;
                     root->_left = prev;
                     if (prev->_right == NULL)
                     {
                           prev->_right = root;
                           prev->_rightTag = THREAD;
                     }
                     prev = root;
              }
              if (root->_leftTag != THREAD)
              {
                     _PrevThreadTree(root->_left, prev);
              }
              if (root->_rightTag != THREAD)
              {
                     _PrevThreadTree(root->_right, prev);
              }
       }
protected:
       Node* _root;
};



中序线索化:
#pragma once
enum
{
       LINK,
       THREAD,
};
template<typename T>
struct ThreadTreeNode
{
       T _data;
       ThreadTreeNode<T> *_left;
       ThreadTreeNode<T> *_right;
       int _leftTag;
       int _rightTag;
       ThreadTreeNode(const T& data)
              :_data(data)
              , _left(NULL)
              , _right(NULL)
              , _leftTag(LINK)
              , _rightTag(LINK)
       {}
};
template<typename T>
class ThreadBinaryTree
{
       typedef  ThreadTreeNode<T> Node;
public:
       ThreadBinaryTree()
              :_root(NULL)
       {}
       ThreadBinaryTree(const T* a,size_t size,const T& invalid)
       {
              size_t index = 0;
              _root =_CreatTree(a,size,index,invalid);
           InThreadTree();
       }
       
       //中序遍历 中序线索化 二叉树
       /*void InOder()
       {
              if (_root == NULL)
                     return;
              Node* cur = _root;
              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;
              }
              cout << endl;
       }*/
       //中序遍历 (2)
       void InOder()
       {
              Node* cur = NULL;
              for (cur = Frist(_root); cur != NULL; cur = Next(cur))
              {
                     cout << cur->_data << " ";
              }
              cout << endl;
       }
       //先序遍历   中序线索化二叉树
       void PrevOder()
       {
              if (_root == NULL)
              {
                     return;
              }
              Node* cur = _root;
              while (cur)
              {
                     while (cur->_leftTag!=THREAD)
                     {
                           cout << cur->_data<<" ";
                           cur = cur->_left;
                     }
                     cout << cur->_data<<" ";
                     if (cur->_rightTag == LINK)
                     {
                           cur = cur->_right;
                     }
                     else
                     {
                           while (cur&&cur->_rightTag == THREAD)
                           {
                                  cur = cur->_right;
                           }
                           if (cur != NULL)
                           {
                                  cur = cur->_right;
                           }             
                     }
              }
              cout << endl;
       }
       //后序遍历 中序线索化二叉树
       void PostOder()
       {
              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=Parent(cur))&&p!=NULL)
              {
                     if (p->_right == cur||p->_rightTag==THREAD)  //如果已经访问完了右子树,或者右子树是线索
                           cur = p;                                  //cur跳转到父节点
                     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:
       //中序线索化二叉树
       void InThreadTree()
       {
              Node* prev = NULL;
              _InThreadTree(_root, prev);
              prev->_rightTag = THREAD;
       }
       Node* Parent(Node* root)          //寻找root结点的父节点
       {
              if (root == NULL || root == _root) //如果root是空结点或根结点,则返回NULL
                     return NULL;
              Node* cur =root;
              while (cur->_leftTag != THREAD)
                     cur = cur->_left;
              if (cur->_left != NULL)
              {
                     for (cur = cur->_left;
                           cur&&cur->_left!=root&&cur->_right!= root;
                           cur = cur->_right);
              }
              if (cur == NULL|| cur->_left == NULL)
              {
                     cur = root;
                     while (cur->_rightTag != THREAD)
                     {
                           cur = cur->_right;
                     }
                     for (cur = cur->_right;
                           cur&&cur->_left != root&&cur->_right != NULL;
                           cur=cur->_left);
              }
              return cur;
       }
       Node* Frist(Node* root)        //寻找以root为根节点的树,中序遍历下的第一个结点
       {
              if (root == NULL)
                     return NULL;
              Node* cur = root;
              while (cur->_leftTag != THREAD)
              {
                     cur = cur->_left;
              }
              return cur;
       }
       Node* Next(Node *root)          //寻找中序遍历下root的后继结点
       {
              if (root == NULL)
                     return NULL;
              Node* cur = root;
              if(cur->_rightTag ==THREAD)
                     return cur->_right;                   //直接返回后继
              return Frist(cur->_right);                 //返回右子树下访问的第一个结点
       }
       Node* Last(Node *root)         //寻找以root为根节点的树,中序遍历下的最后一个结点
       {
              if (root == NULL)
                     return NULL;
              Node* cur = root;
              while (cur->_right==LINK)
                     cur = cur->_right;
              return cur;
       }
       Node* Prior(Node *root)        //寻找中序遍历下root的前继结点
       {
              if (root == NULL)
                     return NULL;
              Node* cur = root;
              if (cur->_leftTag == THREAD)
                     return cur->_left;              //直接返回前继几点
              return Last(cur->_left);            //返回左子树下最后一个访问的结点
       }
       Node* _CreatTree(const T* a, size_t size, size_t& index, const T& invalid)
       {
              //创建一颗二叉树
              Node* root = NULL;
              if (index < size&&a[index] != invalid)
              {
                     root = new Node(a[index]);
                     root->_left = _CreatTree(a, size, ++index, invalid);
                     root->_right = _CreatTree(a, size, ++index, invalid);
              }
              return root;
       }
       //中序线索化二叉树
       void _InThreadTree(Node* root, Node* &prev)
       {
              if (NULL == root)
                     return;
              _InThreadTree(root->_left, prev);
              if (root->_left == NULL)                //线索化前驱
              {
                     root->_leftTag = THREAD;
                     root->_left = prev;
                     prev = root;
              }
              if (prev != root&&prev->_right == NULL)      //线索化后继
              {
                     prev->_rightTag = THREAD;
                     prev->_right = root;
                     prev = root;
              }
              _InThreadTree(root->_right, prev);
       }
protected:
       Node* _root;
};



后序线索化:
#pragma once
enum
{
       LINK,
       THREAD,
};
template<typename T>
struct ThreadTreeNode
{
       T _data;
       ThreadTreeNode<T> *_left;
       ThreadTreeNode<T> *_right;
       ThreadTreeNode<T> *_parent;
       int _leftTag;
       int _rightTag;
       ThreadTreeNode(const T& data)
              :_data(data)
              , _left(NULL)
              , _right(NULL)
              , _parent(NULL)
              , _leftTag(LINK)
              , _rightTag(LINK)
       {}
};
template<typename T>
class ThreadBinaryTree
{
       typedef ThreadTreeNode<T> Node;
public:
       ThreadBinaryTree()
              :_root(NULL)
       {}
       ThreadBinaryTree(const T* a,size_t size,const T& invalid)
       {
              size_t index = 0;
              Node* prev = NULL;
              _root = _CreatTree(a,size,index,invalid,prev);
              PostThreadTree();
       }
       void PostOder()          //后序遍历  后序线索化二叉树
       {
              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* _CreatTree(const T* a,size_t size,size_t& index,const T& invalid,Node* prev)
       {
              Node* root = NULL;
              if (index <size&&a[index] != invalid)
              {
                     root = new Node(a[index]);
                     root->_parent = prev;
                     prev = root;
                     root->_left = _CreatTree(a,size,++index,invalid,prev);
                     root->_right = _CreatTree(a,size,++index,invalid,prev);
              }
              return root;
       }
       void PostThreadTree()        //后序线索化二叉树
       {
              Node* prev = NULL;
              _PostThreadTree(_root,prev);
              if (prev->_right == NULL)
                     prev->_rightTag = THREAD;
       }
       void _PostThreadTree(Node* root,Node* &prev)
       {
              if (root == NULL)
                     return;
              _PostThreadTree(root->_left, prev);
              _PostThreadTree(root->_right, prev);
              if (root->_left == NULL)             //线索化前驱
              {
                     root->_left = prev;
                     root->_leftTag = THREAD;
                     if (prev&&prev->_right == NULL)
                     {
                           prev->_right = root;
                           prev->_rightTag = THREAD;
                     }
                     prev = root;
              }
              else if(prev&&prev->_right==NULL)                 //线索化后继
              {
                     prev->_right = root;
                     prev->_rightTag = THREAD;
                     prev = root;
              }      
       }
protected:
       Node* _root;
};


中序线索化二叉树的迭代器:
#pragma once
#include<cassert>
enum
{
       LINK,
       THREAD,
};
template<typename T>
struct ThreadTreeNode
{
       T _data;
       ThreadTreeNode<T> * _left;
       ThreadTreeNode<T>* _right;
       int _leftTag;
       int _rightTag;
       ThreadTreeNode(const T& data)
              :_data(data)
              , _left(NULL)
              , _right(NULL)
              , _leftTag(LINK)
              , _rightTag(LINK)
       {}
};
template<typename T>
class TreeIterator
{
       typedef ThreadTreeNode<T> Node;
       typedef TreeIterator<T> Iterator;
public:
       TreeIterator()
       {}
       TreeIterator(Node* root)
              :_cur(root)
       {}
       Iterator& operator++()
       {
              assert(_cur);
              if (_cur->_rightTag == THREAD)
                     _cur = _cur->_right;
              else
              {
                     _cur=_cur->_right;
                     while (_cur->_leftTag == LINK)
                           _cur = _cur->_left;
              }
              return *this;
       }
       Iterator& operator--()
       {
              assert(_cur);
              if (_cur->_leftTag== THREAD)
                     _cur = _cur->_left;
              else
              {
                     _cur = _cur->_left;
                     while (_cur->_rightTag == LINK)         //找到_cur的左子树下最后一个访问的结点
                           _cur = _cur->_right;
              }
              return *this;
       }
       Iterator operator++(int)
       {
              assert(_cur);
              Node* cur = _cur;
              if (_cur->_rightTag == THREAD)
                     _cur = _cur->_right;
              else
              {
                     _cur = _cur->_right;
                     while (_cur->_leftTag == LINK)
                           _cur = _cur->_left;
              }
              return cur;
       }
       Iterator operator--(int)
       {
              assert(_cur);
              Node* cur = _cur;
              if (_cur->_leftTag== THREAD)
                     _cur = _cur->_left;
              else
              {
                     _cur = _cur->_left;
                     while (_cur->_rightTag == LINK)         //找到_cur的左子树下最后一个访问的结点
                           _cur = _cur->_right;
              }
              return cur;
       }
       bool operator!=(const Iterator& it)const
       {
              return _cur!= it._cur;
       }
       bool operator==(const Iterator& it)const
       {
              return _cur == it._cur;
       }
       
       T& operator*()
       {
              assert(_cur);
              return _cur->_data;
       }
       T* operator->()
       {
              assert(_cur);
              return &(_cur->_data);
       }
protected:
       Node* _cur;
};
template<typename T>
class ThreadBinaryTree
{
       typedef  ThreadTreeNode<T> Node;
public:
       typedef TreeIterator<T> Iterator;
       ThreadBinaryTree()
              :_root(NULL)
       {}
       ThreadBinaryTree(const T* a, size_t size, const T& invalid)
       {
              size_t index = 0;
              _root = _CreatTree(a, size, index, invalid);
              //中序线索化二叉树
              Node* prev = NULL;
              _InThreadTree(_root, prev);
              prev->_rightTag = THREAD;
       }
       Iterator Begin()                   //获得这棵树第一个访问的结点
       {
              return Frist();
       }
       Iterator End()                      //获得这棵树最后一个访问的结点
       {
              return NULL;
       }
protected:
       Node* Frist()       //返回第一个访问的结点;
       {
              if (_root == NULL)
                     return NULL;
              Node* cur = _root;
              while (cur->_leftTag == LINK)
                     cur = cur->_left;
              return cur;
       }
       Node* _CreatTree(const T* a, size_t size, size_t& index, const T& invalid)
       {
              //创建一颗二叉树
              Node* root = NULL;
              if (index < size&&a[index] != invalid)
              {
                     root = new Node(a[index]);
                     root->_left = _CreatTree(a, size, ++index, invalid);
                     root->_right = _CreatTree(a, size, ++index, invalid);
              }
              return root;
       }
       //中序线索化二叉树
       void _InThreadTree(Node* root, Node* &prev)
       {
              if (NULL == root)
                     return;
              _InThreadTree(root->_left, prev);
              if (root->_left == NULL)                //线索化前驱
              {
                     root->_leftTag = THREAD;
                     root->_left = prev;
                     prev = root;
              }
              if (prev != root&&prev->_right == NULL)      //线索化后继
              {
                     prev->_rightTag = THREAD;
                     prev->_right = root;
                     prev = root;
              }
              _InThreadTree(root->_right, prev);
       }
protected:
       Node* _root;
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值