(Swift 实现)二叉搜索树 —— 创建,最大,最小,查找,插入,删除,前驱,后继,中序遍历

前端之家收集整理的这篇文章主要介绍了(Swift 实现)二叉搜索树 —— 创建,最大,最小,查找,插入,删除,前驱,后继,中序遍历前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

了解了二叉堆之后,二叉搜索树就好说了,就是一个节点,左边的子节点是不可能比他大的,右边的子节点是一定大于它的,想了半天终于把创建给写好了。

创建

  1. import UIKit
  2.  
  3. var str = "二叉搜索树"
  4. //这个就不跟前面的完全二叉树一样了,得自己建了类或者结构体了,我建了个类
  5. class erchaTreeNote {
  6. var data: Int
  7. var leftChild: erchaTreeNote!
  8. var rightChild: erchaTreeNote!
  9. init(data:Int) {
  10. self.data = data
  11. }
  12. }
  13.  
  14. var a = [12,321,432,213,423,4]
  15.  
  16. func createTree() -> (erchaTreeNote) {
  17.  
  18. let root = erchaTreeNote(data:a[0]);
  19. for x in a[1...a.count-1] {
  20.  
  21. let child = erchaTreeNote(data: x)
  22.  
  23. var temp = root
  24. //循环的条件想了半天,想着如何能走下去,在纸上练了几遍,发现了规律,本来进来一个数如果它加进去了,它的左右子节点都是空的,再往下就不走了,但是这个是走不通的,再想他们有什么共性,我就想,既然把它按在了树上,那它再走一次,必然和上一次的路径是一样的,当我找到和它一模一样的时候,就是结束的时候,如果我找不到它,一直都不能结束。就按这个条件走就出来了。
  25.  
  26. while temp !== child {
  27. //如果进来的数小于父节点
  28. if child.data < temp.data {
  29. //不为空,那我就把父节点左边子节点拿上,再重新来过
  30. if temp.leftChild != nil
  31. {
  32. temp = temp.leftChild
  33. }
  34. //当父节点左边是空的时候,那就直接填上
  35. else
  36. {
  37. temp.leftChild = child
  38. print("\(temp.data)左边的孩子")
  39. temp = child //优化语句
  40. }
  41. }else //进来的数大于父节点
  42. {
  43. //不为空,那我就把父节点右边子节点拿上,重新来过
  44. if temp.rightChild != nil {
  45. temp = temp.rightChild
  46. }
  47. //当父节点的右边为空的时候,那就直接补上
  48. else
  49. {
  50. temp.rightChild = child
  51. print("\(temp.data)右边的孩子")
  52. temp = child //优化语句
  53. }
  54. }
  55. }
  56. print(child.data)
  57. }
  58. return root
  59. }
  60. createTree()

最大值和最小值

  1. //找到最大的,那就直接朝右走下去,最小则是朝左走下去
  2. func FindMax(_ shu:erchaTreeNote) -> (erchaTreeNote){
  3. var temp = shu
  4. //如果右边不为空,一直找下去
  5. while temp.rightChild != nil {
  6. temp = temp.rightChild
  7. }
  8. return temp
  9. }
  10. //最小
  11. func FindMin(_ shu:erchaTreeNote) -> (erchaTreeNote){
  12. var temp = shu
  13. //如果左边不为空,一直找下去
  14. while temp.leftChild != nil {
  15. temp = temp.leftChild
  16. }
  17. return temp
  18. }

查找

  1. //找到特定的那个数,这个我发现如果两个一样的数字,可能进入树的时间不一样,所以他们位置也就不一样,得把这棵树可能的条件都循环完毕才可以
  2. func Findfrom(_ shu:erchaTreeNote,_ mubiao:Int) -> ( Array<erchaTreeNote>){
  3. var temp = shu
  4.  
  5. var arr = Array<erchaTreeNote>()
  6.  
  7. while true{
  8. if temp.data < mubiao
  9. {
  10. if temp.rightChild != nil
  11. {
  12. print("拐进右边\(temp.rightChild.data)")
  13. temp = temp.rightChild
  14. }
  15. else
  16. {
  17. print("没有啦")
  18. break
  19. }
  20. }
  21. else if temp.data > mubiao
  22. {
  23. if temp.leftChild != nil
  24. {
  25. print("拐进左边\(temp.leftChild.data)")
  26. temp = temp.leftChild
  27. }
  28. else
  29. {
  30. print("没有啦")
  31. break
  32. }
  33.  
  34. }
  35. else
  36. {
  37. print("找到啦它就是\(temp.data)")
  38. //找到它的时候给它加载数组里,不确定还有没有一样的存在
  39. arr.append(temp)
  40. if (temp.rightChild != nil)
  41. {
  42. print("下面还有东西呢\(temp.rightChild.data)")
  43. temp = temp.rightChild
  44. }
  45. else
  46. {
  47. break
  48. }
  49. }
  50. }
  51. return arr
  52. }

插入

  1. //插入,其实就跟创建是一模一样,只不过多了一个数而已
  2. func insert(_ shu:erchaTreeNote,_ x :Int) -> (erchaTreeNote)
  3. {
  4. func digui (_ ee: erchaTreeNote)
  5. {
  6. if ee.data > x {
  7. if ee.leftChild != nil
  8. {
  9. digui(ee.leftChild)
  10. }
  11. else
  12. {
  13. print("它的父节点是\(ee.data).他在左边")
  14. ee.leftChild = erchaTreeNote(data: x)
  15. }
  16. }
  17. else
  18. {
  19. if ee.rightChild != nil
  20. {
  21. digui(ee.rightChild)
  22. }
  23. else
  24. {
  25. print("它的父节点是\(ee.data).他在右边")
  26. ee.rightChild = erchaTreeNote(data: x)
  27. }
  28. }
  29. }
  30.  
  31. digui(shu)
  32. return shu
  33. }

删除

删除好做,但是得找到那个能顶替它原来位置的节点,我这里只是打印出来,因为没有父节点,不好去找,所以就没做。。

  1. //移除的逻辑也简单易懂,删除这个节点,如果有右节点,再去找右边最小的那个顶上,如果没有右节点,左节点顶上,要是都木有,那就删了
  2.  
  3. func yichu(_ shu:erchaTreeNote,_ x:Int)
  4. {
  5. //先找到这个节点,因为里面可能有重复的情况发生,所以得删个几次,我们从最深的那个删起
  6. let arr = Findfrom(shu,x)
  7. arr.count
  8. for i in 0..<arr.count
  9. {
  10. let temp = arr[arr.count - i - 1]
  11.  
  12. if temp.rightChild != nil
  13. {
  14. print("删了\(temp.data),与\(FindMin(temp.rightChild).data)发生调换")
  15. }
  16. else if temp.leftChild != nil
  17. {
  18. FindMax(temp.rightChild)
  19. print("删了\(temp.data),与\(FindMax(temp.rightChild).data)发生调换")
  20. }
  21. else
  22. {
  23. print("删了\(temp.data),没有发生调换")
  24. }
  25. }
  26. }

前驱

  1. //前驱,一个节点的前驱是指所有比它小的节点里面最大的那个;
  2. func Getpredecessor(_ shu:erchaTreeNote,_ x :Int) -> (erchaTreeNote)
  3. {
  4. let arr = Findfrom(shu,x)
  5. for temp in arr
  6. {
  7. if temp.leftChild != nil
  8. {
  9. return FindMin(temp.leftChild)
  10. }
  11. else
  12. {
  13. return temp
  14. }
  15. }
  16. print("\(x)并没有找到")
  17. return erchaTreeNote(data: -1)
  18. }

后继

  1. //后继,一个节点的后继是指所有比它大的节点里面最小的那个
  2. func GetSuccessor(_ shu:erchaTreeNote,x)
  3. for temp in arr
  4. {
  5. if temp.rightChild != nil
  6. {
  7. return FindMax(temp.rightChild)
  8. }
  9. else
  10. {
  11. return temp
  12. }
  13. }
  14. print("\(x)并没有找到")
  15. return erchaTreeNote(data: -1)
  16. }

中序遍历

  1. //遍历 Inorder Traversal 中序遍历,中序遍历就是先左后右,很直观的输出数字。
  2. func InorderTra(_ shu:erchaTreeNote){
  3.  
  4. var arr = Array<erchaTreeNote>()
  5. func lunhui(_ shu:erchaTreeNote)
  6. {
  7. if shu.leftChild != nil
  8. {
  9. arr.append(shu)
  10. lunhui(shu.leftChild)
  11. }
  12. else
  13. {
  14. print(shu.data)
  15. let beis = arr.remove(at: arr.count-1)
  16. print(beis.data)
  17. if(beis.rightChild != nil) {
  18. lunhui(beis.rightChild)
  19. }
  20. }
  21. }
  22. lunhui(shu)
  23.  
  24. }

就酱,还是蛮有成就感的。要是不对,咱们一起讨论,当然里面的一些极端情况我没有做判断,只是想着熟悉下思路。

猜你在找的Swift相关文章