1. 程式人生 > 其它 >go int 最大值_用Go擼一個二叉搜尋樹

go int 最大值_用Go擼一個二叉搜尋樹

技術標籤:go int 最大值

本來轉自@colobu

https://colobu.com/2020/07/15/implement-bst-in-Go/

前幾天Redis的作者antirez說他朋友面試的時候考到排序問題,然後他說要是他也會考實現一個二叉搜尋樹,我說在中國某公司,據說面試直接就擼一個紅黑樹。不是說你技術渣,試問在座的各位有幾個現在直接裸寫出紅黑樹?

紅黑樹太過偏門,但是常用的二叉搜尋樹你能寫出來嗎?快排呢?堆排序呢?

什麼是二叉搜尋樹

二叉搜尋樹(binary search tree,BST)也叫排序的二叉樹,根節點比左邊子樹的所有節點都大,比右邊子樹上的所有節點都小,如下圖就是一個二叉搜尋樹:

0cdfc45138e894854edffb223954b1aa.png

要實現一個二叉搜尋樹, 我們需要實現節點的插入和刪除,要實現節點的查詢(搜尋),要實現前序遍歷、中序遍歷和後序遍歷,要實現最大節點和最小節點的查詢。

下面就讓我們實現這個二叉搜尋樹。

定義基本資料結構

常規地,我們定義節點的型別,每個節點包含它的值以及左右節點。因為目前Go泛型還沒有釋出,所以這裡我們實現一個元素為int型別的具體的二叉搜尋樹,等泛型實現後可以改成抽象的二叉搜尋樹。

樹只要包含根節點可以了。

// Node 定義節點.type Node struct {  value int   // 因為目前Go的泛型還沒有釋出,所以我們這裡以一個int具體型別為例  left  *Node // 左子節點  right *Node // 右子節點}// BST 是一個節點的值為int型別的二叉搜尋樹.type BST struct {  root *Node}

資料結構有了,接下來就是實現各個方法。

插入和刪除

既然是一棵樹,就需要增加節點用來構造樹,大部分情況下也需要刪除節點。

增加節點的時候,需要判斷應該往左邊子樹上新增,還是往右邊子樹上新增。天然地,既然二叉搜尋樹是一個有序的,那麼我們就可以進行比較,然後遞迴的實現。

// Insert 插入一個元素.func (bst *BST) Insert(value int) {  newNode := &Node{value, nil, nil}  // 如果二叉樹為空,那麼這個節點就當作跟節點  if bst.root == nil {    bst.root = newNode  } else {    insertNode(bst.root, newNode)  }}// 從根節點依次比較func insertNode(root, newNode *Node) {  if newNode.value < root.value { // 應該放到根節點的左邊    if root.left == nil {      root.left = newNode    } else {      insertNode(root.left, newNode)    }  } else if newNode.value > root.value { // 應該放到根節點的右邊    if root.right == nil {      root.right = newNode    } else {      insertNode(root.right, newNode)    }  }  // 否則等於根節點}
刪除有些麻煩,如果是 刪除葉節點就比較容易,刪除即可。 但是如果不是刪除葉節點,那麼就需要將子節點提升。
// Remove 刪除一個元素.func (bst *BST) Remove(value int) bool {  _, existed := remove(bst.root, value)  return existed}// 用來遞迴移除節點的輔助方法.// 返回替換root的新節點,以及元素是否存在func remove(root *Node, value int) (*Node, bool) {  if root == nil {    return nil, false  }  var existed bool  // 從左邊找  if value < root.value {    root.left, existed = remove(root.left, value)    return root, existed  }  // 從右邊找  if value > root.value {    root.right, existed = remove(root.right, value)    return root, existed  }  // 如果此節點正是要移除的節點,那麼返回此節點,同時返回之前可能需要調整.  existed = true  // 如果此節點沒有孩子,直接返回即可  if root.left == nil && root.right == nil {    root = nil    return root, existed  }  // 如果左子節點為空, 提升右子節點  if root.left == nil {    root = root.right    return root, existed  }  // 如果右子節點為空, 提升左子節點  if root.right == nil {    root = root.left    return root, existed  }  // 如果左右節點都存在,那麼從右邊節點找到一個最小的節點提升,這個節點肯定比左子樹所有節點都大.  // 也可以從左子樹節點中找一個最大的提升,道理一樣.  smallestInRight, _ := min(root.right)  // 提升  root.value = smallestInRight  // 從右邊子樹中移除此節點  root.right, _ = remove(root.right, smallestInRight)  return root, existed}

搜尋

檢查一個節點是否存在比較簡單,因為二叉搜尋樹是有序的。

// Search 搜尋元素(檢查元素是否存在)func (bst *BST) Search(value int) bool {  return search(bst.root, value)}func search(n *Node, value int) bool {  if n == nil {    return false  }  if value < n.value {    return search(n.left, value)  }  if value > n.value {    return search(n.right, value)  }  return true}

同時,我們還可以實現查詢一個二叉搜尋樹的最大最小值。

// Min 二叉搜尋樹中的最小值func (bst *BST) Min() (int, bool) {  return min(bst.root)}func min(node *Node) (int, bool) {  if node == nil {    return 0, false  }  n := node  // 從左邊找  for {    if n.left == nil {      return n.value, true    }    n = n.left  }}// Max 二叉搜尋樹中的最大值func (bst *BST) Max() (int, bool) {  return max(bst.root)}func max(node *Node) (int, bool) {  if node == nil {    return 0, false  }  n := node  // 從右邊找  for {    if n.right == nil {      return n.value, true    }    n = n.right  }}

遍歷

可以實現先序遍歷、中序遍歷和後序遍歷,先中後指的是根節點相對子節點的處理順序。

// PreOrderTraverse 前序遍歷func (bst *BST) PreOrderTraverse(f func(int)) {  preOrderTraverse(bst.root, f)}func preOrderTraverse(n *Node, f func(int)) {  if n != nil {    f(n.value) // 前    preOrderTraverse(n.left, f)    preOrderTraverse(n.right, f)  }}// PostOrderTraverse 後序遍歷func (bst *BST) PostOrderTraverse(f func(int)) {  postOrderTraverse(bst.root, f)}func postOrderTraverse(n *Node, f func(int)) {  if n != nil {    postOrderTraverse(n.left, f)    postOrderTraverse(n.right, f)    f(n.value) // 後  }}

是不是你還可以通過廣度搜索按照層級進行遍歷?