排序1 - 选择排序 & 插入排序

请原谅我没有按照之前图片的分类来介绍排序算法,先说最简单的两种排序算法(冒泡略过),选择排序和插入排序,之前老是容易记混。默认输出升序的序列啊,哈哈。

选择排序

对于输入长度为n的数组,一共比较n-1趟,对第 i 趟比较,从第 i 个位置开始,第n个位置结束。找出其中最小元素并记录其位置x, 然后将第 i 个元素和第 x 个元素交换位置。

说白了,第一趟遍历找第一小的元素,第二趟遍历找第二小的元素。。。 多捞啊!

给出伪代码:

selectSort(A)
    n ← A.length;
    
    for i from 0 to n-1 do
        j ← i;
        
        for k from j to n-1 do
            if A[k]<A[j] then
                j ← k;
            end if
        end for
        
        swap A[i] with A[j];
    end for

时间复杂度  = 1+2+...+(n-1) 

→ 时间复杂度为 O(n2),非常稳定,没有最好最坏情况,尴尬。由于没有使用额外空间,空间复杂度为O(1)。

每次插入的元素都和之间的所有元素进行了比较,所以为稳定排序。

 

插入排序

可以分为三步:

  1. 从第2个元素开始,如第 i 个元素,遍历之前索引从 0 到 i-1 的已排序序列,找到自己插入的位置。
  2. 将插入位置到第i-1位置的元素 后移一位
  3. 将第 i 个元素插入。

也即将新元素插入已经排序好的序列中,这个很像机器学习里的在线学习算法,具有学习能力。

给出伪代码:

insertSort(A)
    n ← A.length;
    
    for i from 1 to n-1 do    # n-1 times insert
        insertIndex ← i;
        
        for k from i-1 downto 0 do    # find insertIndex
            if A[k]<A[i] then
                insertIndex ← k+1;
                Break;
            end if
        end for
        flag ← A[i];
        
        for k from i-1 downto insertIndex do    # move back elements
            swap A[k] with A[k+1]
        end for
        
        A[insertIndex] ← flag;    # finish insert
    end for

在第一步中,寻找插入位置,本来顺着找也可以的。但是请思考,如果顺着找,遍历操作和后移操作加在一起,怎么着都需要O(n2)总的时间复杂度。而如果倒着找,就会有最好情况,如输入序列本身有序,那么时间复杂度即为O(n)。

由于没有用到额外空间,故此处空间复杂度为O(1)。

同样,插入元素同插入位置和原位置之间的元素都进行了比较,为稳定排序。

posted @ 2017-12-19 11:45  年华似水丶我如风  阅读(147)  评论(0编辑  收藏  举报