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

创建

import UIKit

var str = "二叉搜索树"
//这个就不跟前面的完全二叉树一样了,得自己建了类或者结构体了,我建了个类
class erchaTreeNote {
    var  data: Int
    var leftChild: erchaTreeNote!
    var rightChild: erchaTreeNote!
    init(data:Int) {
        self.data = data
    }
}

var a = [12,321,432,213,423,4]

func createTree() -> (erchaTreeNote) {

    let root = erchaTreeNote(data:a[0]);
    for x in a[1...a.count-1] {

        let child = erchaTreeNote(data: x)

        var temp = root
        //循环的条件想了半天,想着如何能走下去,在纸上练了几遍,发现了规律,本来进来一个数如果它加进去了,它的左右子节点都是空的,再往下就不走了,但是这个是走不通的,再想他们有什么共性,我就想,既然把它按在了树上,那它再走一次,必然和上一次的路径是一样的,当我找到和它一模一样的时候,就是结束的时候,如果我找不到它,一直都不能结束。就按这个条件走就出来了。

        while temp !== child {
        //如果进来的数小于父节点
            if child.data < temp.data {
            //不为空,那我就把父节点左边子节点拿上,再重新来过
                if temp.leftChild != nil
                {
                    temp = temp.leftChild
                }
             //当父节点左边是空的时候,那就直接填上
                else
                {
                    temp.leftChild = child     
                    print("\(temp.data)左边的孩子")
                    temp = child //优化语句
                }
            }else //进来的数大于父节点
            {
            //不为空,那我就把父节点右边子节点拿上,重新来过
                if temp.rightChild != nil {
                    temp = temp.rightChild
                }
            //当父节点的右边为空的时候,那就直接补上 
                else
                {
                    temp.rightChild = child
                    print("\(temp.data)右边的孩子")
                    temp = child //优化语句
                }   
            }
        }
        print(child.data)
    }
    return root
}
createTree()

最大值和最小值

//找到最大的,那就直接朝右走下去,最小则是朝左走下去
func FindMax(_ shu:erchaTreeNote) -> (erchaTreeNote){
    var temp = shu
    //如果右边不为空,一直找下去
    while temp.rightChild != nil {
        temp = temp.rightChild
    }
    return temp
}
//最小
func FindMin(_ shu:erchaTreeNote) -> (erchaTreeNote){
    var temp = shu
    //如果左边不为空,一直找下去
    while  temp.leftChild != nil {
        temp = temp.leftChild
    }
    return temp
}

查找

//找到特定的那个数,这个我发现如果两个一样的数字,可能进入树的时间不一样,所以他们位置也就不一样,得把这棵树可能的条件都循环完毕才可以
func Findfrom(_ shu:erchaTreeNote,_ mubiao:Int) -> ( Array<erchaTreeNote>){
    var temp = shu

    var arr = Array<erchaTreeNote>()

    while true{
        if temp.data < mubiao
        {
            if temp.rightChild != nil
            {
               print("拐进右边\(temp.rightChild.data)")
               temp = temp.rightChild
            }
            else
            {
                print("没有啦")
                break
            }
        }
        else if temp.data > mubiao
        {
            if temp.leftChild != nil
            {
                print("拐进左边\(temp.leftChild.data)")
                temp = temp.leftChild
            }
            else
            {
                print("没有啦")
                break
            }

        }
        else
        {
            print("找到啦它就是\(temp.data)")
            //找到它的时候给它加载数组里,不确定还有没有一样的存在
            arr.append(temp)
            if (temp.rightChild != nil)
            {
                print("下面还有东西呢\(temp.rightChild.data)")
                temp = temp.rightChild
            }
            else
            {
                break
            }
        }
    }
    return arr
}

插入

//插入,其实就跟创建是一模一样,只不过多了一个数而已
func insert(_ shu:erchaTreeNote,_ x :Int) -> (erchaTreeNote)
{
    func digui (_ ee: erchaTreeNote)
    {
        if ee.data > x {
            if ee.leftChild != nil
            {
                digui(ee.leftChild)
            }
            else
            {
                print("它的父节点是\(ee.data).他在左边")
                ee.leftChild = erchaTreeNote(data: x)
            }
        }
        else
        {
            if ee.rightChild != nil
            {
                digui(ee.rightChild)
            }
            else
            {
                print("它的父节点是\(ee.data).他在右边")
                ee.rightChild = erchaTreeNote(data: x)
            }
        }
    }

    digui(shu)
    return shu
}

删除

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

//移除的逻辑也简单易懂,删除这个节点,如果有右节点,再去找右边最小的那个顶上,如果没有右节点,左节点顶上,要是都木有,那就删了

func yichu(_ shu:erchaTreeNote,_ x:Int)
{
    //先找到这个节点,因为里面可能有重复的情况发生,所以得删个几次,我们从最深的那个删起
    let arr = Findfrom(shu,x)
    arr.count
    for i in 0..<arr.count
    {
        let temp = arr[arr.count - i - 1]

        if temp.rightChild != nil
        {
            print("删了\(temp.data),与\(FindMin(temp.rightChild).data)发生调换")
        }
        else if temp.leftChild != nil
        {
            FindMax(temp.rightChild)
            print("删了\(temp.data),与\(FindMax(temp.rightChild).data)发生调换")
        }
        else
        {
            print("删了\(temp.data),没有发生调换")
        }
    }
}

前驱

//前驱,一个节点的前驱是指所有比它小的节点里面最大的那个;
func Getpredecessor(_ shu:erchaTreeNote,_ x :Int) -> (erchaTreeNote)
{
    let arr = Findfrom(shu,x)
    for temp in arr
    {
        if temp.leftChild != nil
        {
            return FindMin(temp.leftChild)
        }
        else
        {
            return temp
        }
    }
    print("\(x)并没有找到")
    return erchaTreeNote(data: -1)
}

后继

//后继,一个节点的后继是指所有比它大的节点里面最小的那个
func GetSuccessor(_ shu:erchaTreeNote,x)
    for temp in arr
    {
        if temp.rightChild != nil
        {
            return FindMax(temp.rightChild)
        }
        else
        {
            return temp
        }
    }
    print("\(x)并没有找到")
    return erchaTreeNote(data: -1)
}

中序遍历

//遍历 Inorder Traversal 中序遍历,中序遍历就是先左后右,很直观的输出数字。
func InorderTra(_ shu:erchaTreeNote){

    var arr = Array<erchaTreeNote>()
    func lunhui(_ shu:erchaTreeNote)
    {
        if shu.leftChild != nil
        {
            arr.append(shu)
            lunhui(shu.leftChild)
        }
        else
        {
            print(shu.data)
            let beis = arr.remove(at: arr.count-1)
            print(beis.data)
            if(beis.rightChild != nil) {
                lunhui(beis.rightChild)
            }
        }
    }
    lunhui(shu)

}

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

Swift 实现二叉搜索树 —— 创建,最大,最小,查找,插入,删除,前驱,后继,中序遍历的更多相关文章

  1. canvas中普通动效与粒子动效的实现代码示例

    canvas用于在网页上绘制图像、动画,可以将其理解为画布,在这个画布上构建想要的效果。本文详细的介绍了粒子特效,和普通动效进行对比,非常具有实用价值,需要的朋友可以参考下

  2. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. canvas学习和滤镜实现代码

    这篇文章主要介绍了canvas学习和滤镜实现代码,利用 canvas,前端人员可以很轻松地、进行图像处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. localStorage的过期时间设置的方法详解

    这篇文章主要介绍了localStorage的过期时间设置的方法详解的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. 详解HTML5 data-* 自定义属性

    这篇文章主要介绍了详解HTML5 data-* 自定义属性的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  6. HTML5的postMessage的使用手册

    HTML5提出了一个新的用来跨域传值的方法,即postMessage,这篇文章主要介绍了HTML5的postMessage的使用手册的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  7. 教你使用Canvas处理图片的方法

    本篇文章主要介绍了教你使用Canvas处理图片的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  8. ios – Swift语言:如何调用SecRandomCopyBytes

    从Objective-C,我可以这样做:在Swift中尝试这个时,我有以下内容:但我得到这个编译器错误:data.mutableBytes参数被拒绝,因为类型不匹配,但我无法弄清楚如何强制参数.解决方法这似乎有效:

  9. 使用Firebase iOS Swift将特定设备的通知推送到特定设备

    我非常感谢PushNotifications的帮助.我的应用聊天,用户可以直接向对方发送短信.但是如果没有PushNotifications,它就没有多大意义.它全部设置在Firebase上.如何将推送通知从特定设备发送到特定设备?

  10. ios – NSData to Data swift 3

    如何将此代码转换为使用Swift3数据?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部