這一篇是接上一篇文章二叉樹的基本運算
二叉樹的遍歷
二叉樹遍歷分為三種:前序、中序、後序(取決於根節點):
- 前序遍歷:根結點 -> 左子樹 -> 右子樹
- 中序遍歷:左子樹 -> 根結點 -> 右子樹
- 後序遍歷:左子樹 -> 右子樹 -> 根結點
另外還有一種層次遍歷,即每一層都從左向右遍歷。
譬如,對於下面的二叉樹
前序遍歷:abdefgc
中序遍歷:debgfac
後序遍歷:edgfbca
層次遍歷:abcdfeg
實現方法
因為樹的定義本身就是遞迴定義,因此採用遞迴的方法去實現樹的三種遍歷不僅容易理解而且程式碼很簡潔。而對於樹的遍歷若採用非遞迴的方法,就要採用棧去模擬實現。在三種遍歷中,前序和中序遍歷的非遞迴演算法都很容易實現,非遞迴後序遍歷實現起來相對來說要難一點
先序遍歷(非遞迴)
go實現
// 先序遍歷,用棧實現
func preOrderBinaryTree1(root *BinaryTreeNode) {
if root == nil {
return
}
stack := []*BinaryTreeNode{}
top := -1
stack = append(stack, root)
top++
for top >= 0 {
item := stack[top]
stack = stack[:top]
top-- // 出棧
fmt.Print(item.data)
// 先放入右節點
if item.rChild != nil {
stack = append(stack, item.rChild)
top++
}
if item.lChild != nil {
stack = append(stack, item.lChild)
top++
}
}
}
中序遍歷(非遞迴)
go實現
// 中序遍歷,用棧實現
func inOrderBinaryTree1(root *BinaryTreeNode) {
if root == nil {
return
}
stack := []*BinaryTreeNode{}
top := -1
for top >= 0 || root != nil {
for root != nil {
stack = append(stack, root)
top++
root = root.lChild
}
item := stack[top]
stack = stack[:top]
top-- // 出棧
fmt.Print(item.data)
if item.rChild != nil {
root = item.rChild
}
}
}
後序遍歷
// 後序遍歷,用棧實現
func postOrderBinaryTree1(root *BinaryTreeNode) {
if root == nil {
return
}
stack := []*BinaryTreeNode{}
top := -1
var p *BinaryTreeNode = nil
flag := -1
for root != nil {
stack = append(stack, root)
top++
root = root.lChild
}
flag = 1
p = nil
for top != -1 && flag > 0 {
root = stack[top] // 取棧頂元素
if root.rChild == p {
fmt.Print(root.data)
stack = stack[:top]
top-- // 出棧
p = root
} else {
root = root.rChild
flag = 0
}
}
for top != -1 {
for root != nil {
stack = append(stack, root)
top++
root = root.lChild
}
flag = 1
p = nil
for top != -1 && flag > 0 {
root = stack[top] // 取棧頂元素
if root.rChild == p {
fmt.Print(root.data)
stack = stack[:top]
top-- // 出棧
p = root
} else {
root = root.rChild
flag = 0
}
}
}
}