当前位置:   article > 正文

树——二叉排序树(BST)_bst树最好最坏

bst树最好最坏

二叉排序树

  1. 概念
  2. 查找
  3. 插入
  4. 删除(难点)

1、概念

  • 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
  • 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
  • 它的左右子树也分别为二叉搜索树

注:二叉树的中序遍历结果是一个有序数列

2、查找

        给定一个数组,把它变为二叉搜索树

  先定义二叉树结构:

  1. type LinkNode struct{
  2. Val int
  3. Left *LinkNode
  4. Right *LinkNode
  5. }

 注:二叉排序树最好情况为:完全二叉树 O(logn)

                          最坏情况为:退化为单链表O(n)

 二叉树查找:

  1. // 查找
  2. // 类似二分查找的树化
  3. func (root *LinkNode) SearchTree(targer int) *LinkNode {
  4. if root == nil {
  5. return nil
  6. }
  7. for root != nil {
  8. if root.Val > targer {
  9. root = root.Left
  10. } else if root.Val < targer {
  11. root = root.Right
  12. } else {
  13. return root
  14. }
  15. }
  16. return nil
  17. }

3、插入

  1. // 插入数据
  2. // 如果插入的元素已存在,直接返回false
  3. // 需要随时记录父节点的位置
  4. func (root *LinkNode) insertTree(targer int) bool {
  5. node := &LinkNode{Val: targer}
  6. if root == nil {
  7. root.Val = targer
  8. }
  9. var parent *LinkNode
  10. cur := root
  11. for cur != nil {
  12. if cur.Val == targer { // 有重复元素则返回
  13. return false
  14. } else if cur.Val > targer {
  15. parent = cur // 保留当前节点
  16. cur = cur.Left
  17. } else {
  18. parent = cur
  19. cur = cur.Right
  20. }
  21. }
  22. if parent.Val > targer {
  23. parent.Left = node
  24. } else {
  25. parent.Right = node
  26. }
  27. return true
  28. }

4、删除

有两种情况

  1. 被删除节点:左孩子存在,右孩子为空 或者 右孩子存在左孩子为空
  2. 被删除节点:左孩子右孩子都不为空

     解决:

        第一种情况直接让左/右孩子直接代替被删除节点

        第二种情况需要进行 旋转 处理!!!

  1. func (root *LinkNode) remove(targer int) bool {
  2. if root == nil { // 树为空,不存在要删除的节点
  3. return false
  4. }
  5. var parent *LinkNode // 被删除节点的父节点
  6. cur := root // 复制一份
  7. for cur != nil {
  8. if cur.Val == targer {
  9. removeKey(parent, cur)
  10. return true
  11. } else if cur.Val > targer {
  12. parent = cur
  13. cur = cur.Left
  14. } else {
  15. parent = cur
  16. cur = cur.Right
  17. }
  18. }
  19. return false
  20. }
  21. // 处理三种情况(其中两种类似)
  22. func (root *LinkNode) removeKey(parent *LinkNode, cur *LinkNode) {
  23. if cur.Left == nil { // 被刪除节点左孩子为空
  24. if cur == root { // 被删除节点为 根节点
  25. root = root.Right
  26. } else if cur == parent.Left { // 被删除节点 在父节点的左边
  27. parent.Left = cur.Right
  28. } else { // 被删除节点 在父节点的右边
  29. parent.Right = cur.Right
  30. }
  31. } else if cur.Right == nil {
  32. if cur == root {
  33. root = root.Left
  34. } else if cur == parent.Left {
  35. parent.Left = cur.Left
  36. } else {
  37. parent.Right = cur.Left
  38. }
  39. } else { // 处理最复杂的情况。被删除节点左右孩子都不为空
  40. // 一般取被删除节点的右孩子的最小值,替换被删除节点
  41. parentNode := cur // 保存被删除的节点
  42. minNode := cur.Right // 获取被删除节点的右节点(被删除节点的右孩子)
  43. for parentNode != nil {
  44. parentNode = minNode
  45. minNode = minNode.Left
  46. }
  47. // 找到合适的节点(右孩子的最小值)
  48. cur.Val = minNode.Val
  49. if parentNode.Left == minNode {
  50. parentNode.Left = minNode.Right
  51. } else {
  52. parentNode.Right = minNode.Right // 用于处理右孩子为单链表结构
  53. }
  54. }
  55. }

验证:中序遍历

  1. // 中序遍历 用于验证是否成功
  2. func (root *LinkNode) midPrint() []int {
  3. var res []int
  4. var dfs func(*LinkNode)
  5. dfs = func(root *LinkNode) {
  6. if root == nil {
  7. return
  8. }
  9. if root.Left != nil {
  10. dfs(root.Left)
  11. }
  12. res = append(res, root.Val)
  13. if root.Right != nil {
  14. dfs(root.Right)
  15. }
  16. }
  17. dfs(root)
  18. return res
  19. }
  20. func main() {
  21. // 构建二叉树
  22. root := &LinkNode{Val: 4}
  23. root2 := &LinkNode{Val: 2}
  24. root3 := &LinkNode{Val: 6}
  25. root4 := &LinkNode{Val: 1}
  26. root5 := &LinkNode{Val: 5}
  27. root6 := &LinkNode{Val: 7}
  28. root.Left = root2
  29. root.Right = root3
  30. root2.Left = root4
  31. root3.Left = root5
  32. root3.Right = root6
  33. fmt.Println(root.SearchTree(8)) // 查找元素 8
  34. res := root.midPrint()
  35. fmt.Println(res) // 打印中序遍历的二叉树
  36. fmt.Println(root.insertTree(10)) // 插入元素10
  37. fmt.Println(root.remove(4)) // 删除元素4(根节点)
  38. res = root.midPrint()
  39. fmt.Println(res) // 打印中序遍历的二叉树
  40. }

结果:

<nil>
[1 2 4 5 6 7]
true        // 插入成功
true        // 删除成功
[1 2 5 6 7 10]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/274964?site
推荐阅读
相关标签
  

闽ICP备14008679号