数据结构_常见排序算法

排序:将一组杂乱无章的数据按照一定的规律(升序或者降序)组织起来

排序码:用来作为排序的依据,是数据元素的一个属性域

排序算法的稳定性:符合排序码的元素相对位置不发生变化

 

各种常见排序算法的分类:

 

1.冒泡排序:

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

算法思路:

(1)按照升序规则,从前往后冒: 

    [0, bound)  是等待排序的区间

    [bound, size)  是已经有序的区间     (bound,cur 从 0 开始,bound < size -1, cur  > size - bound - 1,cur 从前往后,要小于有效区间)

    从第一个出发,碰见比自己大的就交换位置,交换后继续向后走,直到走到最后,这个时候最大的元素就在最后,第二次还是从第一个开始冒,碰见比自己大的就交换,直到比较倒数第二个(因为最后一个已经是最大的了,不需要在比较)……直到每个元素都比较,每次冒出一个未排序区间最大的元素,下一次就减少一次比较。第一重循环就是一共有多少个元素,第二重循坏是一个元素要比较多少次。

// 交换函数
void Swap1(int* a, int* b)
{   
    *a = *a ^ *b;
    *b = *b ^ *a;
    *a = *a ^ *b;
    return;
}

void Swap2(int* a, int* b)
{   
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
    return;
}

// (以下所有代码使用的交换函数无特别标注,都是Swap3 )
void Swap3(int* a, int* b)
{   
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

// 冒泡排序
// 从前向后冒,降序
//  [bound, size) 代表有序区间
//  [0, bound) 代表等待排序区间
//  cur = 0  从前向后排序
void BubbleSort2(int arr[], int size)
{
    if(arr == NULL || size <= 0){
        return;
    }
    int bound = 0;
    for(; bound < size - 1; bound ++){
        int cur = 0;
        for(; cur < size - bound - 1; cur ++){
            if(arr[cur] < arr[cur + 1]){
                //Swap2(&arr[cur], &arr[cur + 1]);
                Swap3(&arr[cur], &arr[cur + 1]);
            }
        }
    }
    return;
}

(2)按照降序规则,从后往前冒:

    [0, bound)  是已经有序的区间

    [bound, size)  是等待排序的区间 (bound 从0 开始,cur 从 size - 1 开始,bound < size - 1, cur > bound,cur 从后往前,要大于有效区间)

    从最后一个出发,碰见比自己大的就交换位置,交换后继续向前走,直到走到第一个元素,此时第一个元素就是最大的,第二次还是从最后一个开始,直到第二个位置(不需要和第一个比较),这样一直到最后一个,每冒一次,下次就少比较一次。

// 从后往前冒泡,升序
//  [0, bound) 代表有序区间
//  [bound, size) 代表等待排序区间
//  cur = size - 1 从后向前排序
void BubbleSort1(int arr[], int size)
{
    if(arr == NULL || size <= 0){
        return;
    }
    int bound = 0;
    for(; bound < size - 1; bound ++){
        int cur = size - 1;
        for(; cur > bound; cur --){
            if(arr[cur - 1] > arr[cur]){
                Swap1(&arr[cur - 1], &arr[cur]);
            }
        }
    }
    return;
}

 

2.选择排序:

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:不稳定

算法思路:

    (从前向后,升序)每次从边界出发,第一个元素作为擂主(不动),和第二个元素进行比较,如果擂主小,那么不交换值,cur 继续向后走,下一个值继续和擂主比,直到最后一个元素和擂主比较完,这个时候第二个元素称为擂主,从第三个元素开始比较,直到比到最后。每一次打擂台都有可能打乱原有符合排序规则元素之间的原有位置,所以不稳定。

// 选择排序 升序
// [0, bound)  是有序区间
// [bound, size) 是待排序区间
void SelectSort(int arr[], int size)
{
    if(arr == NULL || size <= 0){
        return;
    }
    int bound = 0;
    for(; bound < size; bound ++){
        int cur = bound + 1;
        for(; cur < size; cur ++){
            if(arr[bound] > arr[cur]){
                Swap(&arr[bound], &arr[cur]);
            }
        }
    }
    return;
}

 

3.插入排序:

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

算法思路:

    (升序)     [0, bound)  是已经有序的区间,[bound, size)  是等待排序的区间,bound从 1 开始,cur (cur = bound )来辅助理解完成,前面为一个有序的区间,每次从bound 位置的元素,和有序区间里的元素进行比较,找到一个合适的位置时(边找边搬运,有一个元

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值