排序算法(Swift)

21 篇文章 0 订阅
  • 冒泡排序:它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。时间复杂度: n(n-1)/2 = O(n²)

计算机科学中,算法的时间复杂度是一个函数,它定性描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况。

    func bubbleSort(_ arr : Array<Int>) -> Array<Int> {
        var array = arr
        var num = 0
        //理论上i应该小于array.count-1,因为n个元素只需要进行n-1轮循环比较就能确定n-1个元素,剩下的哪一个元素无需比较就已经确认啦.但是由于内部条件有限制,实际上第n轮循环时i=n-1,这时内部的循环就不再进行啦,所以也不会有问题,但不够严谨.
        for i in 0..<array.count {
            //每完成一次内部循环,就会获取当前循环中的最大值,放在最后位,下次就不用再比较,这就是-i的原因
            for j in 0..<array.count-1-i {
                if array[j] > array[j+1] { //如果是倒叙就<,正序就>
                    array.swapAt(j, j+1)
//                    let temp = array[j+1]
//                    array[j+1] = array[j]
//                    array[j] = temp
//                    print(array)
                }
                num = num + 1
                print(num)
            }
        }
        return array
    }
  • 选择排序 : Selection sort是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

    选择排序算法十分简单易懂,但是它的效率比较低,是O(n^2)。它比插值排序更低效但比冒泡排序更高效。在未排序数组中寻找最小值的过程很慢,而这个过程又是不断被重复的。

//选择排序
func selectionSort(_ arr : Array<Int>) -> Array<Int>{
    var array = arr;
    //有n个数字只需要循环n-1轮就能确定n-1个数字的位置,那么剩下的那一个也就确定了
    for i in 0..<array.count-1{
        //m是用来获得最小(大)数的脚标
        var m = i
        for j in i+1..<array.count{
            if array[j] < array[m]{ //小于号就每次循环获得最小数,大于号就是每次循环获得最大数.
                m = j
                print(m)
            }
        }
        //m是每轮内部循环后标记最小数的脚标,i是要插入的顺序,如果不等就说明该轮需要替换两个数的位置.如果相等就说明当前循环最前的就是最小的数字,不需要替换位置.
        if i != m{
            array.swapAt(i, m)
            print(array)
        }
    }
    return array;
}

关键点在于m是标记每轮最小数的脚标,i是当前已经排序的当前内部循环获得最小数要插入的位置(当前轮最小脚标).

  • 插入排序 : Insertion sort是一种简单直观且稳定的排序算法.选取一个数字,并将其插入在数组里正确的排序位置。比如一个无序的数组A,我先取出第一个元素放入空数组B中,再选取第二个元素,如果比B中元素大就放在后面,否则放在前面,第三次就取A中的第三个元素,和B中的第一个元素比较,如果小就插入到最前面,如果大就和B中的第二个元素比较,如果小就插入到B中的第一个元素和第二个元素之间,如果大就插入到B中的第2个元素后面,依次类推.这个为了便于理解分成了两个数组,其实可以是一个数组,只是要标记哪一部分是已经排序过的,哪一部分是为排序的.具体可参考插入排序. 最坏情况下插入排序的平均情况性能是 O(n ^ 2) (最坏的情况就相当于冒泡排序)
    插入排序
func insertionSort(_ arr: [Int]) -> [Int] {
   var array = arr
   // i相当于分割,即将排序的那一个,0-x是已经排序的d,0-count-1是未排序的,因为第一个元素移过去不需要比较排序所以从1开始,还是需要n-1次外部循环
   for i in 1..<array.count {
       var index = i       
  //在while循环之前index是未排序的,index-1及以前都是已经排序后的,循环之后index位就是已排序的了,因为是从后往前比,一但找到合适的位置(array[index] < array[index - 1]),就不在会继续往下比较了,就插入进去(array.swapAt(index - 1, index))
       while index > 0 && array[index] < array[index - 1] {  //小于号是正序排列,大于号是倒序排列
           array.swapAt(index - 1, index)
           print(array)
           //防止数组取值脚标越界,-1是不能为数组脚标的
           index -= 1
       }
   }
   return array
}
  • 折半查找: 也叫折半搜索(英语:half-interval search),又称二分搜索(英语:binary search)、对数搜索(英语:logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半.
func binarySearch<T: Comparable>(_ a: [T], key: T) -> Int? {
    //小脚标
    var lowerBound = 0
    //大脚标
    var upperBound = a.count
    //循环查找的条件是小脚标必须小于大脚标
    while lowerBound < upperBound {
        //取中间脚标 lowerBound + (upperBound - lowerBound) / 2
        let midIndex = (lowerBound+upperBound)/2
        //如果中间脚标的值等于目标值,则返回该脚标
        if a[midIndex] == key {
            return midIndex
        //如果中间脚标的值比目标值小,则将最小脚标设置为比现在的中间脚标大1,然后进行下一次循环
        } else if a[midIndex] < key {
            lowerBound = midIndex + 1
        //如果中间脚标的值比目标值大,则将最大脚标设置为现在的中间脚标,为什么不减1,因为这样就可能出现找不到边界值的情况,比如a = [1,22],key = 1,这时候如果是upperBound = midIndex- 1返回的就是nil
        } else {
            upperBound = midIndex
        }
    }
    return nil
}

注意:这边查找的前提是数组已经是有序的,并且不能有重复数字.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值