📌算法Go语言描述📌treestruct📌1-bst.go
package treestruct

type BstNode struct {
	Value int      // 值
	Count int      // 值出现次数
	Left  *BstNode // 左子树
	Right *BstNode // 右子树
}
type BinarySearchTree struct {
	Root *BstNode // 根结点
}

func (tree *BinarySearchTree) Search(v int) *BstNode {
	for p := tree.Root; p != nil; {
		if p.Value == v {
			return p
		}
		if v < p.Value {
			p = p.Left
		} else {
			p = p.Right
		}
	}
	return nil
}

func (tree *BinarySearchTree) Min() *BstNode {
	if tree.Root == nil {
		return nil
	}
	res := tree.Root
	for res.Left != nil {
		res = res.Left
	}
	return res
}

func (tree *BinarySearchTree) Max() *BstNode {
	if tree.Root == nil {
		return nil
	}
	res := tree.Root
	for res.Right != nil {
		res = res.Right
	}
	return res
}

func (tree *BinarySearchTree) Insert(v int) {
	if tree.Root == nil {
		tree.Root = &BstNode{Value: v, Count: 1}
		return
	}
	p := tree.Root
	for {
		if v == p.Value {
			p.Count++
			return
		}
		if v < p.Value {
			if p.Left == nil {
				p.Left = &BstNode{Value: v, Count: 1}
				return
			}
			p = p.Left
		} else {
			if p.Right == nil {
				p.Right = &BstNode{Value: v, Count: 1}
				return
			}
			p = p.Right
		}
	}
}

/*
Delete 值所在结点的不同情况:
未找到不作任何处理,无子树直接删除。
有两个子树,右子树的最小值(或左子树最大值)所在结点替换被删的结点。
有一个子树,该子树直接替换被删的结点(优于按两个子树的逻辑处理)。

	    p?                 p?
	    |                 ||
	  3(c)               4(s)
	  /  \              // \\
	2     8            2    8
		 / \               / \
	   6(t) 9   ==>      6(t) 9
	   / \               // \
	 4(s) 7             5    7
	 \
	  5

3(c)右子树的最小元素是4(s),将s移动到3(c)的位置,s.Left拼上原c.Left。
当t!=c即s!=c.Right时,还需将t.Left拼上原s.Right(含nil),再将s.Right拼上原c.Right。
最后当p!=nil时将p和s连接上,p==nil时s直接设为根结点。
*/
func (tree *BinarySearchTree) Delete(v int) {
	var p *BstNode
	for c := tree.Root; c != nil; {
		if v == c.Value {
			if c.Count > 1 {
				c.Count--
			} else {
				var s *BstNode     // 删除c后的新子树的根结点
				if c.Left == nil { // 左子树为空,右子树替换
					s = c.Right // 包含了两个子树均为空的case
				} else if c.Right == nil { // 右子树为空,左子树替换
					s = c.Left
				} else { // 左右子树均不为空,右子树的最小元素替换待删除结点(Left,Right反过来则是左子树的最大元素替换待删除结点)
					t := c      // 右子树最小结点的双亲结点
					s = c.Right // 右子树最小结点
					for s.Left != nil {
						t = s
						s = s.Left
					}
					s.Left = c.Left // 新的根结点拼接待删除结点的左子树
					if t != c {     // 也即 s != c.Right
						t.Left = s.Right  // parent结点拼接取出元素的子树
						s.Right = c.Right // 新根结点拼接待删除结点的右子树
					}
				}
				if p == nil {
					tree.Root = s
				} else {
					if v < p.Value { // 是其左结点
						p.Left = s
					} else { // 是其右结点
						p.Right = s
					}
				}
			}
			return
		}
		p = c
		if v < c.Value {
			c = c.Left
		} else {
			c = c.Right
		}
	}
}

// InOrderTraversal 中序遍历返回有序数组
func (tree *BinarySearchTree) InOrderTraversal() []int {
	var res []int
	tree.Root.inOrderTraversal(&res)
	return res
}
func (node *BstNode) inOrderTraversal(res *[]int) {
	if node != nil {
		node.Left.inOrderTraversal(res)
		for i := 0; i < node.Count; i++ { // 重复值
			*res = append(*res, node.Value)
		}
		node.Right.inOrderTraversal(res)
	}
}