遍歷二叉樹是以一定規則將二叉樹中結點排列成一個線性序列即是對一個非線性結構進行線性化操作,使除第一個和最后一個節點外,每一個節點有且只有一個直接前驅,直接后繼
二叉樹作為存儲結構只能找到節點的左孩子右孩子信息,而不能直接得到結點在任一序列中的前驅和后繼,這種信息只有在遍歷的動態過程中可以看到。
二叉樹線索化可以利用二叉樹中指向左右子樹的空指針來存放節點的前驅和后繼信息可以使用以下結點結構:
enum pointertag{ Link, Thread };
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T>* _left;
BinaryTreeNode<T>* _right;
pointertag _lefttag, _righttag;
BinaryTreeNode(const T&x)
:_data(x)
, _left(NULL)
, _right(NULL)
, _lefttag(Link)
, _righttag(Link)
{}
};
1、二叉樹的中序線索化
void _InOrderThding(BinaryTreeNode<T>*cur, BinaryTreeNode<T>*&prev) { if (cur == NULL) return; _InOrderThding(cur->_left, prev);//左子樹 if (cur->_left == NULL)//當節點的左孩子為空時線索化 { cur->_lefttag = Thread; cur->_left = prev; } if (prev&&prev->_right == NULL)//當線索化結點3的后繼時,由於指向根節點2,即當前cur指向的結點
{ prev->_righttag = Thread; prev->_right = cur; } prev = cur;//prev記錄cur上一個指向的結點 _InOrderThding(cur->_right, prev);//右子樹 }
2、二叉樹的前序線索化
void _PrevOrderThding(BinaryTreeNode<T>*cur, BinaryTreeNode<T>*&prev) { if (cur == NULL) return; if (cur->_left == NULL))//當cur->_left為空時,_lefttag的狀態變為Thread,進行線索化 { cur->_lefttag = Thread; cur->_left = prev; } if (prev&&prev->_right == NULL) { prev->_righttag = Thread; prev->_right = cur; } prev = cur; if (cur->_lefttag == Link)//只有當結點的_lefttag的狀態為link時,需要遞歸線索化左子樹 2、 3的_lefttag==Thread,即不用進入此遞歸
{
_PrevOrderThding(cur->_left, prev);
1、cur->_left為3
} if (cur->_righttag == Link)//3、3的_righttag為Link進入,3的右子樹為NULL此層循環return,cur指向結點2,prev指向結點3 { _PrevOrderThding(cur->_right, prev); }
3、二叉樹的后序線索化
void _PostOrderThding(BinaryTreeNode<T>*cur, BinaryTreeNode<T>*&prev) { if (cur == NULL) return; _PostOrderThding(cur->_left, prev); _PostOrderThding(cur->_right, prev); if (cur->_left == NULL) { cur->_lefttag = Thread; cur->_left = prev; } if (prev&&prev->_right == NULL) { prev->_righttag = Thread; prev->_right = cur; } prev = cur; }