十大经典排序(一) —— 插入、希尔

前言

十大经典排序 —— 前言

1、插入排序

思想

从前向后遍历,将待排序的元素插入前面已经排序好的子序列中,直到全部元素插入完成

图解

插入排序

直接插入排序

原理

顺序查找找到插入的位置

代码

void InsertSort(int *a, int n) {
    int i, j, t;
    for (i = 1; i < n; i++) {
        if (a[i] < a[i - 1]) {
            t = a[i];
            for (j = i - 1; j >= 0 && a[j] > t; j--) {
                a[j + 1] = a[j];
            }
            a[j + 1] = t;
        }
    }
}

适用性

适用于顺序表、链表

折半插入排序

原理&步骤

折半查找找到插入的位置

以从小到大排序为例,首先用key存储需要排序的数据

1、折半查找——用 l o w 、 m i d 、 h i g h low、mid、high lowmidhigh划分两个区域 [ l o w , m i d − 1 ] [low,mid-1] [lowmid1] [ m i d + 1 , h i g h ] [mid+1,high] [mid+1high]

2、判断——如果key值小于序列的中间值 [ m i d ] [mid] [mid],则代表key值应该插入左边的区域 [ l o w , m i d − 1 ] [low,mid-1] [lowmid1],然后对 [ l o w , m i d − 1 ] [low,mid-1] [lowmid1]再重复划分区域,直到 l o w > h i g h low>high low>high 为止

3、插入——最后的插入位置应该是 h i g h + 1 high+1 high+1,先将high之后位置的数据整体后移,然后将key赋值给 [ m i d + 1 ] [mid+1] [mid+1],完成插入

代码

void InsertSort(int *a, int n) {
    int i, j, low, high, mid, key;
    for (i = 1; i <= n; i++) {
        key = a[i];
        low = 0;
        high = i - 1;
        while (low <= high) {
            mid = (low + high) / 2;
            if (a[mid] > key) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        for (j = i - 1; j >= high + 1; j--) {
            a[j + 1] = a[j];
        }
        a[high + 1] = key;
    }
}

适用性

仅适用于顺序表

复杂度

时间复杂度:

最好:全部有序: O ( n ) O(n) O(n)

最坏:全部逆序: O ( n 2 ) O(n^2) O(n2)

平均: O ( n 2 ) O(n^2) O(n2)

折半插入排序比较次数减少,但是移动次数没变,时间复杂度还是: O ( n 2 ) O(n^2) O(n2)

空间复杂度: O ( 1 ) O(1) O(1)

稳定性

插入排序是稳定的,因为相同元素的相对位置没变,如果两个元素相同,插入元素放在相同元素后面。

2、希尔排序

原理&步骤

希尔排序,也称缩小增量排序,也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本

步骤如下:

1、先将整个元素序列切割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序

2、然后依次缩减增量再进行排序,待整个序列中的元素基本有序,即增量足够小时,再对全体元素进行一次直接插入排序。

3、由于直接插入排序在元素基本有序的情况下,接近最好情况,效率是非常高的,因此希尔排序在时间效率上有较大提高。

图解

希尔排序

代码

void ShellSort(int *a, int n) {
    int d, i, j, t;
    for (d = n / 2; d >= 1; d /= 2) {
        for (i = d; i < n; i++) {
            if (a[i] < a[i - d]) {
                t = a[i];
                for (j = i - d; j >= 0 && a[j] > t; j -= d) {
                    a[j + d] = a[j];
                }
                a[j + d] = t;
            }
        }
    }
}

复杂度

时间复杂度:

最好:根据情况而定

最坏: O ( n s )   1 < s < 2 O(n^s) \ 1<s<2 O(ns) 1<s<2

平均: O ( n l o g n ) O(nlogn) O(nlogn)

空间复杂度: O ( 1 ) O(1) O(1)

稳定性

希尔排序是不稳定的

适用性

仅适用于顺序表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值