Contents

Binary Tree

二元樹是一種樹狀的資料結構,本文章將會介紹六種不同的二元樹及如何實作。

Introduction

Binary Tree

二元樹是一種分層式的資料結構,由 Node 組成且每個 Node 最多只能有 2 個 Child ,分別稱為 Left Node 和 Right Node 。

Node 由以下三點組成:

  • data element
  • pointer of left node
  • pointer of right node

Types of Binary Tree

Full Binary Tree

Full Binary Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

每個 Node 都有 0 或 2 個 Child 時,稱為 Full Binary Tree 。

Complete Binary Tree

Complete Binary Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

Complete Binary Tree 跟 Full Binary Tree 很相似,但有以下幾點不同。

  1. 除了最後一層之外,所有層都必須被完整填充
  2. 最後一層(Leaf Layer)從左邊開始填充
  3. 最後一個 Leaf(6) 可能會沒有 Right Sibling

Perfect Binary Tree

Perfect Binary Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

所有 Leaf 都在同一層,且除了 Leaf 之外的 Node 都有 2 個 Child 。

Degenerate or Pathological Tree

Degenerate or Pathological Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

稱為退化樹或病態樹,除了 Leaf 之外,每個 Node 都有一個 Child ,不是 Left Node 就是 Right Node 。

Skewed Binary Tree

Skewed Binary Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

也是退化樹/病態樹的一種,其 Child 全部都在左側或右側。依照向左或向右傾斜又可分為 Left-Skewed Binary TreeRight-Skewed Binary Tree

Balanced Binary Tree

Balanced Binary Tree
圖片來源 https://www.programiz.com/dsa/binary-tree

每個 Node 的 Left Subtree 和 Right Subtree 高度只相差 1 或 0 。

Implement Bainary Tree

用 Linked List 實作 Binary Tree ,完整程式碼

Declare Structure

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
type Node struct {
	value int
	left, right *Node
}

type BinaryTree struct {
	root *Node
}

func createNode(value int) *Node {
	return &Node{value: value}
}

func newBinaryTree(value int) *BinaryTree {
	return &BinaryTree{
		root: &Node{value: value},
	}
}

第 1 ~ 4 行:宣告 Node 有三個屬性,分別是資料跟 Left Node 和 Right Node 。
第 6 ~ 8 行:宣告名稱為 Binary Tree 的 Linked List 。
第 10 ~ 12 行:建立 Node 的方法。
第 14 ~ 18 行:建立 Linked List 的方法。

Implement Count the Number of Node in a Tree

1
2
3
4
5
6
7
func (root *Node) GetNodeCount() int {
	if root == nil {
		return 0
	}

	return root.left.GetNodeCount() + root.right.GetNodeCount() + 1
}

使用 recursion 實作計算該樹共有多少 Node 。

Implement Count Degree of a Tree

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func (root *Node) GetTreeDegree() int {
	if root != nil {
		var maxDegree int
		queue := append([]*Node{}, root)
		for len(queue) != 0 {
			element := queue[0]
			queue = queue[1:]
		
			var degree int
			if element.left != nil {
				degree += 1
				queue = append(queue, element.left)
			}

			if element.right != nil {
			    degree += 1
			    queue = append(queue, element.right)
			}

			if degree > maxDegree {
			    maxDegree = degree
			}
		}
		return maxDegree
	}
	return 0
}

實作計算樹的 Degree 。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func (root *Node) Search(value int) (*Node, error) {
	if root != nil {
		queue := append([]*Node{}, root)
		for len(queue) != 0 {
			element := queue[0]
			queue = queue[1:]
			if element.value == value {
				return element, nil
			}

			if element.left != nil {
				queue = append(queue, element.left)
			}
			
			if element.right != nil {
				queue = append(queue, element.right)
			}
		}
	}

	return &Node{}, errors.New("the value not exist in node of a tree")
}

實作搜尋資料是否存在樹中的 Node 。

Implement Preorder Traversal

1
2
3
4
5
6
7
func (root *Node) Preorder() {
	if root != nil {
		fmt.Printf("-> %v ", root.value)
		root.left.Preorder()
		root.right.Preorder()
	}
}

使用 recursion 實作前序遍歷。
前序遍歷的輸出順序為: Root -> Left Node -> Right Node

Implement Inorder Traversal

1
2
3
4
5
6
7
func (root *Node) Inorder() {
	if root != nil {
		root.left.Inorder()
		fmt.Printf("-> %v ", root.value)
		root.right.Inorder()
	}
}

使用 recursion 實作中序遍歷。
中序遍歷的輸出順序為: Left Node -> Root -> Right Node

Implement Postorder Traversal

1
2
3
4
5
6
7
func (root *Node) Postorder() {
	if root != nil {
		root.left.Postorder()
		root.right.Postorder()
		fmt.Printf("-> %v ", root.value)
	}
}

使用 recursion 實作後序遍歷。
後序遍歷的輸出順序為: Left Node -> Right Node -> Root

Implement Layer-Order Traversal

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func (root *Node) LayerOrder() {
	if root == nil {
		return
	}

	var queue []*Node
	queue = append(queue, root)
	for len(queue) != 0 {
		node := queue[0]
		queue = queue[1:]
		fmt.Printf("-> %v ", node.value)
		if node.left != nil {
			queue = append(queue, node.left)
		}
		
		if node.right != nil {
			queue = append(queue, node.right)
		}
	}
}

使用 queue 實作階層式遍歷。
階層式遍歷的輸出順序為先輸出 Root 再依序 Left Node -> Right Node 輸出。