二叉樹的遍歷,就是按照一定的規則訪問二叉樹,
將二叉樹的非線性結構轉換為二叉樹結點的乙個線性序列
假設 l, r, v 分別代表遍歷乙個結點的左子樹,右子樹,以及訪問該結點的操作
則遍歷總共有六種規則:
vlr
vrl
------ 前序
lvr
rvl
------ 中序
lrv
rlv
------ 後序
為了方便,以下演算法都採用先左後右的三種,先右後左同理
當樹非空時:按照順序訪問,若是l或者r則遞迴訪問,遇到v就直接訪問.
中序遍歷的遞迴演算法:
template void binarytree::inorder(bintreenode*subtree, void(*visit)(bintreenode*p))
}
前序遍歷的遞迴演算法:
template void binarytree::preorder(bintreenode*subtree, void(*visit)(bintreenode*p))
}
後序遍歷的遞迴演算法:
template void binarytree::postorder(bintreenode*subtree, void(*visit)(bintreenode*p))
}
為了把乙個遞迴過程改寫為乙個非遞迴過程需要利用乙個工作棧,記錄遍歷時的回退路徑
前序遍歷時,當前結點的訪問時機就是當前,
所以只需要在訪問左或者右的時候用棧暫存另一邊即可
第一種
初始化:p取根結點,棧變為空
迴圈: 訪問結點
預留右子樹指標在棧中
左子樹非空則進入左子樹,左子樹為空則彈出右子樹,下一次迴圈訪問的就是右子樹
template void binarytree::preorder(void(visit)(bintreenode*p))
}
另外一種方法:
初始化:根結點入棧
迴圈: p取棧頂元素,訪問p
如果右子樹存在,右子樹進棧
如果左子樹存在,左子樹進棧
template void binarytree::preorder(void(visit)(bintreenode*p))
}
中序遍歷時,當前結點的訪問時機是左孩子為空或者左孩子訪問完了
所以棧用來存放當前結點,當左孩子為空時就是訪問的時機,
演算法描述:
初始化:棧為空,p取根結點
重複以下操作
當p不為空時,p進棧,p指向其左孩子,直到p左為空
若棧非空,出棧乙個,訪問,p指向其右孩子
直到p為空,且棧為空(do-while結構)
template void binarytree::inorder(void(*visit)(bintreenode*p))
//執行到此處,說明前乙個p的左孩子為空
//所以此時應該訪問前乙個p的父結點,即棧中最後進入的元素
if (!s.isempty())
} while (p != null || !s.isempty());
}
結束條件為棧為空且遍歷指標為空。
棧不為空,遍歷指標為空表示左子樹訪問完了,該訪問棧裡面的結點了
棧為空,但指標不為空時表示右子樹還沒訪問。
後序遍歷的乙個重要性質:當前訪問節點的時候,工作棧內的元素順序剛好是其祖先結點到它的路徑
後序遍歷的非遞迴比前序和中序複雜。
在遍歷左子樹時不能訪問根結點,還要遍歷右子樹。
右子樹遍歷完了才能訪問根結點。
所以我們要搞清楚的是上次訪問時在左子樹中還是右子樹中。
方法一(結點中增加標誌域):
即每次入棧時,要同時給進棧結點乙個標記,在訪問完左子樹時,還要把棧頂結點的標記改為右。
經過分析,訪問結點的時機就是其右孩子為空或者右孩子訪問完了的時候
總結演算法步驟:
初始化:棧為空,p取根結點
重複以下操作:
當p不為空時,進棧,標記為左,直到左孩子為空
定義乙個標記,用於判斷是否處於左子樹,賦值真
當處於左子樹且棧非空時,
取出棧頂元素,
判斷標記:
如果是左標記,將其改為右,再放進去,左子樹標記改為假,並指向其右孩子
如果是右標記,訪問
直到棧為空
template void binarytree::postorder(void(*visit)(bintreenode*p))
int continue1 = 1;
while (continue1 %% !s.isempty())
}} while (!s.isempty());
cout << endl;
}
方法二(增加輔助指標,記錄最後一次訪問的結點):
當 p非空或棧非空時:
如果p非空,則p的左孩子進棧
否則:p取棧頂元素
如果p右孩子存在且上次沒被訪問,p指向右孩子
否則:出棧
訪問p元素
記錄訪問的結點
p置空
另一種寫法:
p取根結點,last取root,根結點進棧
當棧非空時:
p取棧頂元素
如果,左右孩子都存在或者右孩子為空last為左孩子或者last為右孩子
訪問p指向結點,last設為p,s出棧
否則:如果右孩子存在,右孩子進棧
如果左孩子存在,左孩子進棧
方法三:
p取根結點,棧s為空
p進棧兩次
當棧非空時:
p取棧頂元素,s出棧
如果棧非空且p等於棧頂元素
若p右孩子存在,右孩子進棧兩次
若p左孩子存在,左孩子進棧兩次
否則:訪問p指向的結點
入隊順序即出隊順序,也就是訪問順序
入隊時一定要,先上後下,先左後右
初始化:p取根結點,根結點入佇列
當佇列非空時:
出佇列,訪問出來的元素
如果出來的元素有左孩子,則其左孩子入佇列
如果出來的元素有右孩子,則其右孩子入佇列
template void binarytree::levelorder(void(*visit)(bintreenode*p))
}
mysql 遍歷二叉樹 資料結構 二叉樹遍歷
這篇博文主要是研究二叉樹遍歷的遞迴與非遞迴演算法,有興趣的小夥伴可以了解下!二叉樹的遞迴遍歷 深度優先遍歷 先來張圖,看看各結點遍歷時的情況 二叉樹深度優先遍歷總結 分別為第一次,第二次,第三次進入某個結點 先序遍歷 先訪問根結點,然後先序遍歷左子樹,最後先序遍歷右子樹 根 左 右 中序遍歷 先中序...
資料結構 遍歷二叉樹
資料結構實驗之二叉樹二 遍歷二叉樹 time limit 1000ms memory limit 65536kb submit statistic problem description 已知二叉樹的乙個按先序遍歷輸入的字串行,如abc,de,g,f,其中,表示空結點 請建立二叉樹並按中序和後序的方...
資料結構 遍歷二叉樹
二叉樹的遍歷原理 二叉樹的遍歷是指從根節點出發,按照某種次序以此訪問二叉樹所有節點,使得每個節點被訪問一次且僅被訪問一次 二叉樹遍歷方法 1.前序遍歷 規則是若二叉樹為空,則空操作返回,否則先訪問根節點,然後前序遍歷左子樹,再前序遍歷右子樹 2.中序遍歷 規則是若樹為空,則空操作返回,否則從根節點開...