排序算法(2)——简单选择排序和直接插入排序

简单选择排序

简单选择排序就是通过关键字之间的比较,在记录里面找到最小(或者最大)的数字,并同当前位置交换之。

贴个代码:

void SelectSort(SqList *L)
{
    int i, j, min;
    for (i = 0; i < L->length - 1; i++)
    {
        min = i;
        for (j = i + 1; j < L->length; j++)
        {   
            if (L->r[min] > L->r[j])
            {
                 min = j;
            }
        }
        if (i != min)
            swap(L, i, min);
    }
}

分析一下:很显然,对于一个无序数组来说,把第一个数的下标暂且作为值最小的下标,然后通过与其后的数据对比,找出真正的最小的数组的下标,如果找到,就交换,如果没找到,说明当前数据是最小的,那么就不用交换。然后下标递增,再次比较。就这样实现排序。

复杂度分析:

我们知道,交换最多需要n - 1次(最少需要0次)。而第i次排序需要n - i 次比较,那么总共有 (n - 1) + (n - 2) +  (n - 3) +..... + 1 = n * (n - 1) / 2次比较,显然时间复杂度就是O(n ^ 2)(但是比起冒泡排序来说,简单选择的性能还是要比冒泡好一点。

直接插入排序

直接插入排序,就是将一个记录插入到已经排好序的有序表中,从而得到一个新的有序表。

先给出代码,稍后分析:

void InsertSort(SqList *L)
{
    int i, j;
    for (i = 2; i < L->length; i++)  //下标从2开始。
    {
        if ( L->r[i] < L->r[i - 1])
        {
            L->r[0] = L->r[i];
            for (j = i - 1; L->r[j] > L->r[0]; j--)
                L->r[j + 1] = L->r[j];
            L->r[j + 1] = L-> r[0];  //注意上面有j--,所以这里空出来的位置应该是j + 1
    }
}

代码分析:如上(升序排序),我们举个栗子,有一个无序数组{5, 3, 2, 4 , 6},现在要把它给拍好,怎么做呢?

首先,我们把r[1] = 5当作是有序的一个数组(这里的L->r[0]必须要空出来当哨兵),即:{ 5 };那么现在我们需要将剩下的{3, 2, 4, 6}插入到{5}这个有序表中,显然现在的问题就是插入到5左边还是右边了,为此,下标从2开始,循环比较两两之间的大小,如果后者比前者小,那么就把后者的值赋值给哨兵,再把前者适当的往后移动(这里的适当是有条件的,也就是L->r[j] > L->r[0],即到出现比哨兵小的数据为止)。移动完之后再把哨兵的值赋值给移动出来的空位。

复杂度分析:如果要排序的数组一开始就是有序的,那么只需要比较次数,时间复杂度为O(n),而最坏的情况(数组完全逆序),那么这个时候,当外循环等于2(总共执行n - 2次)时,内循环执行了n - 1次,当外循环等于3时,执行了n - 2次。。。。。。所以,总的执行次数为 n - 2 + n - 3 + ....+  1 = ( n-1) * (n - 2) / 2,也就是O(n^2)。虽然是平方阶,但是它的性能比冒泡和简单选择要好的多。

以上。

下次写希尔排序和堆排序

原来人类的悲欢并不相通, 我只觉得他们吵闹。
原文地址:https://www.cnblogs.com/zhlabcd/p/9104136.html