二叉樹的線索化

2021-07-29 17:05:47 字數 3275 閱讀 7183

在上篇博文中我們說到有關二叉樹的遍歷問題,將樹中的所有結點按照某種次序排列在乙個線性有序的序列中,然後從某個結點出發就會可以輕易找到在某種次序下的前驅和後繼。

然而當我們希望快速找到某一結點的前驅後繼,同時又不希望對二叉樹進行遍歷時,這時就需要乙個東西去把每個結點的前驅後繼記錄儲存起來。為了做到這一點,資料結構引出乙個概念叫線索。就好比在某種次序下用一根線將這棵樹的前驅後繼儲存起來,使得乙個前驅指標指向前驅結點,乙個後繼指標指向後繼結點。

我們可以用乙個結構體來對儲存這些結點,在這裡用列舉對前驅和後繼進行標記。

enum

pointer

;struct binarytreenodethd

當我們做完這些的時候就可以考慮我們怎麼去實現線索化。

1.中序線索二叉樹

在中序線索化中,如果_lefttag==link,那表示在_left中儲存的是左孩子結點的指標;如果_lefttag==thread,即_left中儲存的是指向前驅的指標。_righttag也同理。

首先判斷當前結點,如果當前結點是根結點,那麼就遞迴找到它的最後乙個葉子結點,即圖中3這個結點。現在對3進行前驅線索化,使得_lefttag等於thread。緊接著對它進行後繼線索,因為3沒有左孩子和右孩子,所以接下來我們需要對4進行線索化。

在這裡我們需要借用乙個pre的指標,讓它在遍歷的過程中總是指向在中序遍歷下的前驅結點,即在中序遍歷中剛剛訪問過的結點。同理,4 的前驅結點為2,後繼結點為1……一定要注意:當我們遇到空指標時就根據情況填入前驅或後繼線索。

void _inorderthreading(node* cur, node*& prev)   //中序線索化

if (prev && prev->_right ==

null) //建立當前結點的後繼線索

prev = cur; //前驅跟上,當前結點向前遍歷

_inorderthreading(cur->_right, prev); //遞迴,右孩子線索化

}

2.前序線索二叉樹前序線索在思想上和中序線索是一樣的,區別僅是加入前驅和後繼的時間不同。線索表示如下圖。

首先先考慮根,然後在對它的左孩子和右孩子進行處理。當乙個結點是葉子結點時,它需要把前驅鏈結到它的父結點上,用pre儲存上乙個訪問的結點(在這裡也就是父結點),然後再次訪問它父結點的右孩子……依此類推,對於每個結點都做這樣的處理,把大問題不斷變成子問題,然後對其進行處理。**如下。

void _prevorderthreading(node* root, node*& prev)

if (prev && prev->_right ==

null)

prev = root;

if (root->_lefttag ==

link)

_prevorderthreading(root->_left, prev);

if (root->_righttag ==

link)

_prevorderthreading(root->_right, prev);

}

對二叉樹的線索化,思路都是從大問題不斷細化縮小實現,一定要明白它的線索是怎麼個線索法:有孩子結點就存孩子結點的指標,沒有孩子結點就指向前驅或後繼。

最後附上源**。

#include

using

namespace

std;

enum pointer

;template

struct binarytreenodethd

};template

class binarytreethd

//lefttag==0 left中存放的是指向左孩子結點的指標

//lefttag==1 left中存放的是該結點中序下的前驅結點指標

void inorderthreading() //中序線索化

void inorderthd() //中序線索化遍歷

cout

<< cur->_data << " ";

while (cur->_righttag == thread)

cur = cur->_right;

}cout

<< endl;

}void prevorderthreading()

void prevorderthd()

cout

<< cur->_data << " ";

cur = cur->_right;

}cout

<< endl;

}protected:

node* _creattree(t* a, size_t n, const t& invalid, size_t& index)

return root;

}void _inorderthreading(node* cur, node*& prev)

if (prev && prev->_right == null) //建立當前結點的後繼線索

prev = cur; //前驅跟上,當前結點向前遍歷

_inorderthreading(cur->_right, prev); //遞迴,右孩子線索化

}void _prevorderthreading(node* root, node*& prev)

if (prev && prev->_right == null)

prev = root;

if (root->_lefttag == link)

_prevorderthreading(root->_left, prev);

if (root->_righttag == link)

_prevorderthreading(root->_right, prev);

}protected:

node* _root;

};

(C )二叉樹的線索化 線索二叉樹

線索化標誌tag enum pointertag 結點結構 template struct binarytreenodethd 基類迭代器 template struct binarytreeiterator t operator t operator bool operator const sel...

線索化二叉樹以及遍歷線索化二叉樹

1.線索二叉樹基本介紹 n個結點的二叉鍊錶中含有n 1 公式 2n n 1 n 1 個空指標域。利用二叉鍊錶中的空指標域,存放指向該結點在某種遍歷次序下的前驅和後繼結點的指標 這種附加的指標稱為 線索 這種加上了線索的二叉鍊錶稱為線索鍊錶,相應的二叉樹稱為線索二叉樹 threaded binaryt...

線索化二叉樹

define crt secure no warnings 1 includeusing namespace std enum pointertag 列舉 其結構如下 void prevorderthreading 前序 void postorderthreading 後序 void inorder...