/*****/二叉樹基礎問題

創建一棵二叉樹(先序創建):

以{1,2,3,’#’,’#’,4,’#’,’#’,5,6}爲例:
先創建左路,每創建一個結點就入棧,cur指向當前結點:

這裏寫圖片描述

左路創建完畢之後用一個變量top保存棧頂元素3,然後將棧頂的元素3拋出:
這裏寫圖片描述
然後再創建top的右子樹且cur=top->_right,然後再重複上述操作,直到創建完畢。

非遞歸:  
       TreeNonR(const T* a, size_t size, const T& invalid)  
       {  
              Node* cur = NULL;  
              stack<Node*> s;  
              size_t index = 0;  
              while (index < size)  
              {  
                     while (index < size&&a[index] != invalid)  
                     {  
                           if (index == 0)                     //根節點特殊處理  
                           {  
                                  _root = new Node(a[index++]);  
                                  cur = _root;  
                           }  
                           else  
                           {  
                                  cur->_left = new Node(a[index++]);  
                                  cur = cur->_left;  
                           }  
                           s.push(cur);  
                     }  
                     index++;  
                     Node* top = s.top();  
                     s.pop();  
                     if (index < size&&a[index] != invalid)  //如果右子樹的根節點不爲空再創建  
                     {  
                           cur = top;  
                           cur->_right = new Node(a[index++]);  
                           cur = cur->_right;  
                           s.push(cur);  
                     }  
              }  
       }  

遞歸:  
       BinaryTree(const T *array,size_t size,const T& invalid)  
       {  
              size_t index = 0;  
              _root=_CreatTree(array,size,index,invalid);  
       }  

       Node* _CreatTree(const T *array, size_t size, size_t& index, const T& invalid)  
       {  
              assert(array);  
              Node *root=NULL;  
              if (index < size&&array[index] != invalid)  
              {  
                     root = new Node(array[index]);                                  //創建根節點  
                     root->_left = _CreatTree(array,size,++index,invalid);           //遞歸創建左子樹  
                     root->_right= _CreatTree(array,size,++index,invalid);           //遞歸創建右子樹  
              }  
              return root;  
       }  

1.前序遍歷一棵二叉樹:
BinaryTreeTopic.h

//面向過程
#pragma once
namespace BT_TOPIC
{
    struct Node
    {
        Node* _left;
        Node* _right;
        int _data;

        Node(int  x)
            :_data(x)
            ,_left(NULL)
            ,_right(NULL)
        {}
    };
    //前序遍歷
    void PrevOrder(Node* root)
    {
        if (root == NULL)
            return;
            cout << root->_data << "";
            PrevOrder(root->_left);
            PrevOrder(root->_right);
        }
void test1()
        {
            Node* n1 = new Node(1);
            Node* n2 = new Node(2);
            Node* n3 = new Node(3);
            Node* n4 = new Node(4);
            Node* n5 = new Node(5);
            Node* n6 = new Node(6);

            n1->_left = n2;
            n1->_right = n5;

            n2->_left = n3;
            n2->_right = n4;

            n5->_left = n6;

            PrevOrder(n1);
            cout << endl;
        }
    }

test.cpp

#include<iostream>
#include<assert.h>
using namespace std;
#include "BinaryTreeTopic.h"


int main()
{
    BT_TOPIC::test1();
    return 0;
}

這裏寫圖片描述
中序遍歷

 void InOder()      //中序遍歷  
       {  
              _InPrint(_root);  
              cout << endl;  
       }  
       void _InPrint(Node *root)  
       {  
              Node *cur = root;  
              if (cur)  
              {  
                     _InPrint(cur->_left);  
                     cout << cur->_data << " ";  
                     _InPrint(cur->_right);  
              }  
       }  

後序遍歷:

遞歸:  
       void PostOder()      //後序遍歷  
       {  
              _BackPrint(_root);  
              cout << endl;  
       }  
       void _BackPrint(Node *root)  
       {  
              Node *cur = root;  
              if (cur)  
              {  
                     _PostPrint(cur->_left);  
                     _PostPrint(cur->_right);  
                     cout << cur->_data << " ";  
              }  
       }  

2.銷燬
BinaryTreeTopic.h

void DestoryTree(Node*& root)
        {
            if (root == NULL)
                return;
            DestoryTree(root->_left);
            DestoryTree(root->_right);
            delete root;
            root = NULL;
        }

3.求二叉樹節點的個數:
BinaryTreeTopic.h

//面向過程
#pragma once
namespace BT_TOPIC
{
    struct Node
    {
        Node* _left;
        Node* _right;
        int _data;

        Node(int  x)
            :_data(x)
            , _left(NULL)
            , _right(NULL)
        {}
    };
    ////求二叉樹節點的個數  //全局/靜態-》線程安全問題
    void _GetTreeSize(Node* root, size_t& size)
    {
        if (root == NULL)
            return;

        ++size;
        _GetTreeSize(root->_left, size);
        _GetTreeSize(root->_right, size);
    }
    size_t GetTreeSize(Node* root)
    {
        if (root == NULL)
            return 0;
        return GetTreeSize(root->_left) +
            GetTreeSize(root->_right) + 1;
    }



    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        cout << "Size?" << GetTreeSize(n1) << endl;

    }
}

非遞歸:  
       size_t Size()  
       {  
              size_t count = 0;  
              Node* cur = _root;  
              stack<Node*> s;  
              while (cur || !s.empty())  
              {  
                     while (cur)  
                     {  
                           count++;        //遍歷一個結點就讓count++  
                           s.push(cur);  
                           cur = cur->_left;  
                     }  
                     Node * top = s.top();  
                     s.pop();  
                     cur = top->_right;  
              }  
              return count;  
       }  

4.求葉子節點的個數:
BinaryTreeTopic.h

//面向過程
#pragma once
namespace BT_TOPIC
{
    struct Node
    {
        Node* _left;
        Node* _right;
        int _data;

        Node(int  x)
            :_data(x)
            , _left(NULL)
            , _right(NULL)
        {}
    };
    //求葉子節點的個數:
    size_t GetLeafSize(Node* root)
    {
        if (root == NULL)
            return 0;
        if (root->_left == NULL&&root->_right == NULL)
        {
            return 1;
        }
        return GetLeafSize(root->_left)
            + GetLeafSize(root->_right);
    }
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        cout << "Size?" << GetSize(n1) << endl;

    }
}

這裏寫圖片描述

非遞歸:  
       size_t Leaft()  
       {  
              size_t count = 0;  
              Node* cur = _root;  
              stack<Node*> s;  
              while (cur || !s.empty())  
              {  
                     while (cur)  
                     {  
                           //如果左右子樹都爲空,則爲葉子結點  
                           if (cur->_left == NULL&&cur->_right == NULL)  
                                  count++;  
                           s.push(cur);  
                           cur = cur->_left;  
                     }  
                     Node * top = s.top();  
                     s.pop();  
                     cur = top->_right;  
              }  
              return count;  
       }  

5.求第k層節點個數:

size_t GetKLevel(Node* root, size_t k)
    {
        if (root == NULL)
            return 0;
        if (k == 1)
            return 1;
        return GetKLevel(root->_left, k - 1)
            + GetKLevel(root->_right, k - 1);

    }
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        cout << "K Level" << GetKLevel(n1,2) << endl;

    }
}

這裏寫圖片描述

求第i層的結點的個數
非遞歸:使用隊列,將每一層的元素的個數都統計出來。

 size_t GetLeveSize(size_t i)  
       {  
              //空樹返回0  
              if (NULL == _root)  
                     return 0;  
              //第0或第1層返回層號  
              if (i<=1)  
                     return i;  
              queue<Node*> q;  
              q.push(_root);  
              size_t leve =1;              //標記層號  
              size_t  NodeNum = 1;          //統計有多少數據入過隊  
              size_t  LeveLast = 1;         //標記正在訪問的這層的最後一個數據的序號  
              size_t  VisitNum = 0;         //統計已經有多少數據已經出隊  
              while (!q.empty())  
              {  
                     Node* cur = q.front();  
                     q.pop();  
                     VisitNum++;  
                     if (NULL != cur->_left)  
                     {  
                           q.push(cur->_left);  
                           NodeNum++;  
                     }  
                     if (NULL != cur->_right)  
                     {  
                           q.push(cur->_right);  
                           NodeNum++;  
                     }  

                     if (VisitNum == LeveLast)   //如果以出隊的個數等於這一層的最後一個數據的序號  
                     {  
                           leve++;  
                           if (leve == i)  
                                  break;   
                           LeveLast = NodeNum;        //更新到下一層的最後一個數據的位置  
                     }  
              }        
              //用已經入隊過的數據個數減去已經出隊的個數,得到要求的這一層的個數  
              return NodeNum - VisitNum;    
       }  

6.判斷一個節點是否在一棵二叉樹中

bool IsInTree(Node* root, int x)
    {
        if (root == NULL)
        {
            return false;
        }
        if (root->_data == x)
        {
            return true;
        }
        return IsInTree(root->_left, x) || IsInTree(root->_right, x);
    }
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        cout << "Is in Tree?" << IsInTree(n1, 6) << endl;

    }
}

這裏寫圖片描述

7.層序遍歷一棵二叉樹:
8.//判斷一棵樹是否是完全二叉樹

9.求二叉樹中節點的最遠距離:

int _FindMaxLen(Node* root, int& maxLen)
{
    if (root == NULL)
        return 0;
    int left = _FindMaxLen(root->_left, maxLen);
    int right = _FindMaxLen(root->_left, maxLen);

    if ((left +right ) > maxLen)
    {
        maxLen = left + right;
    }
    return left > right ? left + 1 : right + 1;
}

10.非遞歸遍歷

//非遞歸前序遍歷
void PrevOrderNonR(Node* root)
{
    Node* cur = root;
    stack<Node*> s;
    while (cur || !s.empty())
    {
        //1.訪問一棵樹的開始
        //這些節點的右子樹還沒訪問,依次從棧裏面取出來訪問
        while (cur)
        {
            cout << cur->_data << "";
            s.push(cur);
            cur = cur->_left;
        }
        Node* top = s.top();
        s.pop();
        cur = top->_right;
    }
    cout << endl;
}
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        PrevOrderNonR(n1);
        cout << endl;

    }
}
//非遞歸中序遍歷
void InOrderNonR(Node* root)
{
    stack<Node*> s;
    Node* cur = root;
    while (cur || !s.empty())
    {
        //訪問一棵樹的開始
        while (cur)
        {
            s.push(cur);
            cur = cur->_left;
        }
        //棧裏面取出來意味着左子樹已經訪問過了
        Node* top = s.top();
        s.pop();
        cout << top->_data << "";
        //子問題
        cur = top->_right;
    }
    cout << endl;
}
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        InOrderNonR(n1);
        cout << endl;

    }
}

//非遞歸後序遍歷
void PostOrderNonR(Node* root)
{
    Node* prev = NULL;
    Node* cur = root;
    stack<Node*> s;
    while (cur || !s.empty())
    {
        while (cur)
        {
            s.push(cur);
            cur = cur->_left;
        }
        Node* top = s.top();
        if (top->_right == NULL || top->_right == prev)
        {
            cout << top->_data << "";
            prev = top;
            s.pop();
        }
        else
        {
            cur = top->_right;
        }
    }

}
    void test1()
    {
        Node* n1 = new Node(1);
        Node* n2 = new Node(2);
        Node* n3 = new Node(3);
        Node* n4 = new Node(4);
        Node* n5 = new Node(5);
        Node* n6 = new Node(6);

        n1->_left = n2;
        n1->_right = n5;

        n2->_left = n3;
        n2->_right = n4;

        n5->_left = n6;

        PostOrderNonR(n1);
        cout << endl;

    }
}

11.查找一個結點:

非遞歸:  
Node* Find(const T& x)  
       {  
              Node* cur = _root;  
              stack<Node*> s;  
              while(cur||!s.empty())  
              {  
                     while (cur)  
                     {  
                           if (cur->_data == x)         //如果找到則直接返回  
                                  return cur;  
                           s.push(cur);  
                           cur = cur->_left;  
                     }  
                     Node* top = s.top();  
                     s.pop();  
                     cur = top->_right;  
              }  
              return NULL;  
       }  

遞歸:  
       Node* Find(const T& x)  
       {  
              return _Find(_root,x);  
       }  
       Node* _Find(Node* root,const T& x)  
       {  
              if (root == NULL)  
                     return NULL;  
              if (root->_data == x)  
                     return root;  
              Node* cur = _Find(root->_left,x);  
              if (cur == NULL)  
                     cur = _Find(root->_right,x);  
              return cur;  
       }  

12.求樹的深度:

非遞歸:藉助隊列,一層一層的訪問,每訪問完一層,deep加一,直到隊列爲空,則求得深度。

size_t Depth()  
       {  
              if (_root == NULL)  
                     return 0;  
              queue<Node*> q;  
              size_t deep = 0;              
              size_t  NodeNum = 1;      //統計有多少數據入過隊  
              size_t  LeveLast = 1;      //標記正在訪問的這層的最後一個數據的序號  
              size_t  VisitNum=0;       //統計已經出隊的數據的個數  
              q.push(_root);  
              while (!q.empty())  
              {  
                     Node* cur =q.front();  
                     q.pop();  
                     VisitNum++;  
                     if (NULL != cur->_left)  
                     {  
                           q.push(cur->_left);  
                           NodeNum++;  
                     }  
                     if (NULL != cur->_right)  
                     {  
                           q.push(cur->_right);  
                           NodeNum++;  
                     }  
                     //如果以出隊的個數等於這一層的最後一個數據的序號  
                     if (LeveLast == VisitNum)      
                     {  
                           deep++;                //訪問完一層就讓深度加一  
                           LeveLast = NodeNum;    //更新到下一層的最後一個數據的位置  
                     }  
              }  
              return deep;  
       }  

遞歸:  
       size_t Depth()          //求深度  
       {  
              return _Depth(_root);  
       }  
       size_t _Depth(Node *root)  
       {  
              Node *cur = root;  
              if (NULL == cur)  
                     return 0;  
              size_t left = _Depth(cur->_left);  
              size_t right = _Depth(cur->_right);  
              return left > right ? left + 1 : right + 1;  
       }  

線索化二叉樹爲我們提供了一種不需要遞歸和藉助棧就能遍歷一顆二叉樹的方法,如果將二叉樹寫成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;  
};  
發佈了123 篇原創文章 · 獲贊 15 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章