数据结构之排序--插入类排序

一. 插入类排序

1. 直接插入排序

      待排数列初始状态是正序,反序,无序时的时间复杂度为O(n), O(n^2), O(n^2)

      是稳定的排序算法


2. 二分插入排序


3.希尔排序

    希尔排序优于直接插入排序。理由:1> 当待排数列大致有序时,比较和移动的次数较少(比较后才移动,比较的少自然移动的少,移动的少比较的也少)

       2> 当待排数列元数个数较少时,n 与 n^2 的差距也小。即O(n)与O(n^2)差不多

       3>希尔排序刚开始时,增量大,分组多,之后增量减少,分组减少,组内元素增加,但却大致有序,故希尔排序在效率上较直接插入排序有较大的改进!

    希尔排序是不稳定的算法,即相同关键字排序后的相对顺序()会改变


插入类排序的基本思想是:把无序区的记录按关键字大小,插入已排好的有序区内!


1. 直接插入排序

 大体思路:a>把无序区的记录按关键字大小,插入已排好的有序区内!

                  b>单趟具体如何插入?把无序区的待排记录,从后向前与有序区的元素相比,不一定比较到第一个元素!

    void insert_sort(int a[], int len)
{
    int i, j;
    int tmp;

    for (i = 1; i < len; i++) {
        tmp = a[i];

        for (j = i - 1; j >= 0; j--) {
            if (tmp >= a[j])                        // 此处tmp改成a[j + 1]呢? tmp是待排元素! a[j + 1]呢?
                break;
            a[j + 1] = a[j];                          // 此处仅是后移,不是交换! 整个外层与内层循环才是交换,所以也可以写个SWAP宏来实现,不过效率降低了
        }   

        a[j + 1] = tmp;
    }   

    return ;
}


2. 二分法插入排序

int binary_search(int a[], int len, int x)
{
    int left, right;

    left = 0;
    right = len - 1;

    while (left <= right) {
        int mid = (left + right) / 2;

        if (x > a[mid])
            left = mid + 1;
        else if (x = a[mid])
            return mid;
        else
            right = mid - 1;
    }

    return left;
}

void binary_sort(int a[], int len)
{
    int i, j, n;
    int tmp;

    for (i = 1; i < len; i++) {
        tmp = a[i];
        n = binary_search(a, i, tmp);

        for (j = i - 1; j >= n; j--) {
            a[j + 1] = a[j];
        }   

        a[j + 1] = tmp;
    }   

}

待排数列:9, 8, 3, 1, 7, 4, 10, 14
输入结果:3  1  4  7  8  9  10  14

检查了几遍,一是算法,符合逻辑,应该没问题  二调用也应该没问题。。。不知到该检查什么了。。。

后来不注意看到 else if (x = a[mid])....比较表达式,怎么成赋值了啊!知道哪里有问题了.............脑子不是很清醒时,就易犯这种很二的错误,并别检查了几遍都没看出来!

所以,三应该检查语言本身容易出错的地方,如“==” 写成 "="


3.希尔排序

大体思路:取一个小于len的数d1作为第一个增量,把待排数列分为d1组,所有距离为d1的元数为一组,在组内进行直接插入排序;

                然后取第二个增量d2 (d2 < d1),重复上述分组和排序。直至所取的增量dt = 1时,即所有的元素放在一个组内进行插入排序为止!该方法实质上是分组方法!

void shell_sort(int a[], int len)
{
    int gap = len / 3;

    while (gap) {
        int i, j;
        int tmp;

        for (i = 0; i < len - gap; i++) {            //需改! 从第一序列的第二个元素开始扫描,对首先出现的各子序列的第二个元素 ,分别在各子序列中进行插入处理。。直到各子序列最后一个元素
            tmp = a[i];
            for (j = i - gap; j >= 0; j = j - gap) {
                if (a[j + gap] >= a[j])
                    break;
                a[j + gap] = a[j];
            }   

            a[j + gap] = tmp;
        }   

        gap = gap - 1;
    }   
}
另一种方法:每次比较后,进行交换

void  shellSorting(T data[], size_t len)
{
    int gap = len;
    int i, j;

    while (gap /= 2) {
        for (i = 1 ; i < len - gap; i++) {
            for (j = i + gap; j >= gap; j--)            // for (j = i + gap; j >= 0; j = j - gap)
                if (data[j - gap] > data[j])
                    SWAP(data[j - gap], data[j]);
        }   
    }   
}

********************************************

不足 :变量命名??

  3 void shellsorting(int ary[], int len)
  4 {
  5     int i, j;                             //放到循环 内
  6     int d = len / 3;
  7     int tmp;                          //同上
  8
  9     while (d <= 1)                //while (d)
 10     {
 11         for (i = d; i < len; i++)
 12         {
 13             tmp = ary[i];
 14
 15             for (j = i - d; j >= 0; j  = j - d)
 16             {
 17                 if (tmp >= ary[j])
 18                     break;
 19                 ary[j + d] = ary[j];
 20             }
 21             ary[j + d] = tmp;
 22         }
 23
 24         d--;
 25     } } 

你可能感兴趣的:(C/C++)