1. 程式人生 > >二叉樹的線索化演算法思想詳解

二叉樹的線索化演算法思想詳解

    二叉樹的線索化,這幾天以來我很難掌握,今天終於想通了,哈哈,首先我們來看看二叉樹線索化之後會變成什麼樣子,這裡我們以圖中的二叉樹為例,圖如下:

wKioL1clqWXAc9hmAAAeyeZzebo767.png

    畫的太糙,各位看官講究著看吧- -。所謂二叉樹的線索化,就是當一個節點的左右指標為空時,就讓它的左右指標指向該節點的前驅或者後繼(一般來說左指標指向前驅,右指標指向後繼)。這裡不論指向前驅或者後繼,我們都應該線索化時,至少要明確兩個節點指標的值,當前節點和當前節點的前驅/後繼。這也是線索化的兩種思路:

    儲存前驅:訪問當前節點時若當前節點的左指標為空,則令左指標指向前驅,若前驅的右指標為空,則令前驅的右指標指向當前節點,程式碼描述如下:

void visit(NODE* cur,NODE* &prev)//當前指標的前驅在當前指標訪問時會改變,故傳引用用來改變//prev
{
       if(prev->right==NULL;
           prev->right=cur;
       if(cur->left==NULL)
           cur->left=prev;
       prev=cur;
}

    這裡我們要注意的是應該先進行訪問,最後再改變prev的值。

    儲存後繼:這種方法很難做到,並且個人覺得沒有什麼意義,因為在遍歷整個數的過程中我們始終都會訪問到一個節點的後繼,若將要訪問後繼那我們如何儲存到未來的東西,即使通過類似棧的資料結構通過壓棧來強行訪問,效率也是不高的,在此不推薦。

    接下來獻上c++完整的線索二叉樹結構以及中序線索化過程,通過遞迴與非遞迴兩種方式實現,其他的都大同小異。

    節點類定義如下:

typedef char Datatype;
enum NodeType
{
	LINK,
	THERAD
};

struct TheardBinaryTreeNode
{
	TheardBinaryTreeNode* _left;
	TheardBinaryTreeNode* _right;
	NodeType _leftTag;
	NodeType _rightTag;
	Datatype _data;
	TheardBinaryTreeNode(const Datatype & data)
		:_left(NULL)
		, _right(NULL)
		, _leftTag(LINK)
		, _rightTag(LINK)
		,_data(data)
	{}
	TheardBinaryTreeNode()
		: _left(NULL)
		, _right(NULL)
		, _leftTag(LINK)
		, _rightTag(LINK)
		,_data((Datatype)0)
	{}
};

    中序線索化如下:

	void InTherad()
	{
		NODE* prev = NULL;
		_InTherad(_root, prev);
		//stack<NODE*>s;//藉助棧來實現非遞迴的中序線索化
		//NODE* cur = _root;
		//NODE* prev = NULL;
		//while (!s.empty()||cur)
		//{
		//	while (cur)
		//	{
		//		s.push(cur);
		//		cur = cur->_left;
		//	}
		//	NODE* top = s.top();
		//	s.pop();
		//	if (top->_left == NULL&&top->_leftTag == LINK)
		//	{
		//		top->_left = prev;
		//		top->_leftTag = THERAD;
		//	}
		//	prev = top;
		//	if (top->_right == NULL&&top->_rightTag==LINK)
		//	{
		//		top->_rightTag = THERAD;
		//		if (!s.empty())
		//			top->_right = s.top();
		//	}
		//	else
		//		cur = top->_right;
		//}
	}
		void _InTherad(NODE*root, NODE* &prev)//遞迴的中序線索化
	{
		if (root == NULL)
			return;
		_InTherad(root->_left, prev);
		if (prev&&prev->_rightTag == LINK&&prev->_right == NULL)
		{
			prev->_right = root;
			prev->_rightTag = THERAD;
		}
		if (root->_leftTag == LINK&&root->_left == NULL)
		{
			root->_leftTag = THERAD;
			root->_left = prev;
			prev = root;
		}
		_InTherad(root->_right,prev);
	}

    如有不足或者疑問希望留言提出。3Q -3-。