数组排序算法

以下原理及实现均为个人理解,如有错误或更优解,欢迎留言指正!

排序算法概述

盗个图

转自:https://www.cnblogs.com/onepixel/articles/7674659.html

排序算法复杂度

 

备注:以下排序算法默认由小到大排序

 

 

  • 交换排序

 

 

 

  • 冒泡排序

算法简介

 
  1. 从右向左依次对比相邻元素,将较小值交换到左边;
  2. 每一轮循环可将最小值交换到最左边;
  3. 下一轮从之后的位置开始重复1,2 过程,直至完成整个数组。

算法实现

int bubble_sort(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        return -1;
    }

    int tmp = 0;
    int i = 0, j = 0;
    for(i=0; i<len; i++)
    {
        for(j=len-1; j>i; j--)
        {
            if(array[j-1] > array[j])
            {
                tmp = array[j-1];
                array[j-1] = array[j];
                array[j] = tmp;
            }
        }
    }

    return 0;
}

 

 

 

  • 快速排序

算法简介

 
  1. 选择一个元素赋值给哨兵sentinel,默认选择左边第一个元素,这样第一个元素的位置就空出来了;
  2. 先从最右边元素开始依次跟哨兵比较大小,大于等于哨兵的元素原地不动,遇到小于哨兵的元素则终止循环,把该元素赋值到左侧空出来的位置,同时左侧索引值自增,这时该元素原来的位置就空出;
  3. 然后从左侧元素开始依次跟哨兵比较大小,小于等于哨兵的元素原地不动,遇到大于哨兵的元素则终止循环,把该元素赋值到右侧空出来的位置,同时右侧索引值自减;
  4. 依次循环2,3 步,直至左侧索引等于右侧索引,则完成一轮循环,把哨兵赋值到该索引位置。
  5. 再分别递归地对哨兵左侧和右侧的子数组进行1,2,3,4 步,直至递归子数组只有一个元素,则排序

算法实现

int quick_sort_core(int array[], int left, int right)
{
    if(NULL == array || left < 0 || right < left)
    {
        printf("params error!\n");
        return -1;
    }

    int l = left, r = right;
    int sentinel = array[l];

    while(l < r)
    {
        while((l < r) && array[r] > sentinel)
        {
            r--;
        }
        if(l < r)
        {
            array[l++] = array[r];
        }

        while((l < r) && array[l] < sentinel)
        {
            l++;
        }
        if(l < r)
        {
            array[r--] = array[l];
        }
    }

    array[l] = sentinel;

    if(l > left)
    {
        quick_sort_core(array, left, l-1);
    }
    if(r < right)
    {
        quick_sort_core(array, r+1, right);
    }

    return 0;
}

int quick_sort(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        printf("params error!\n");
        return -1;
    }

    int i = 0;
    int left = 0, right = len - 1;
    int result = quick_sort_core(array, left, right);
    if(result != 0)
    {
        return -1;
    }

    return 0;
}

 

 

  • 插入排序

 

 

 

  • 直接插入排序

算法简介

 
  1. 左边第一个元素可作为有序子数组;
  2. 从第二个元素开始,依次向前比较,大于该元素的则向右移一位,直到比该元素小的元素,插入其后;
  3. 依次向后推进,直至整个数组成为有序数组

算法实现

int insert_sort(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        return -1;
    }

    int tmp = 0;
    int i = 0, j = 0;
    for(i = 1; i < len; i++)
    {
        tmp = array[i];
        for(j = i-1; j >= 0 && tmp < array[j]; j--)
        {
            array[j+1] = array[j];
        }
        array[j+1] = tmp;
    }

    return 0;
}
  • 希尔排序

算法简介

 
  1. 首先选择一个步长值gap,以步长值为间隔把数组分为gap个子数组 i + n*gap,i < gap;
  2. 对每个子数组进行插入排序;
  3. 逐步减小步长 gap = gap/3 + 1,重复对数组进行1,2 步骤;
  4. 当步长值减为1时,相当于对数组进行一次直接插入排序。

算法优点

相对于直接插入排序,希尔排序要高效很多,因为当gap 值较大时,对子数组进行插入排序时要移动的元素很少,元素移动的距离很大,这样效率很高;在gap逐渐减小过程中,数组中元素已逐渐接近排序的状态,所以需要移动的元素逐渐减少;当gap为1时,相当于进行一次直接插入排序,但是各元素已接近排序状态,需要移动的元素很少且移动的距离都很小。

算法实现

int shell_sort(int array[], int len)
{
    if(NULL == array || len < 1)
    {
        return -1;
    }

    int tmp = 0;
    int i = 0, j = 0, k = 0, gap = len;
    do
    {
        gap = gap/3 + 1;
        for(i = 0; i < gap; i++)
        {
            for(j = i+gap; j < len; j = j+gap)
            {
                tmp = array[j];
                for(k = j-gap; k >= i && tmp < array[k]; k = k-gap)
                {
                    array[k+gap] = array[k];
                }
                array[k+gap] = tmp;
            }
        }
    } while(gap > 1);

    return 0;
}
  • 选择排序

 

 

 

  • 简单选择排序

算法简介

 
  1. 从右向左依次对比相邻元素,将较小值交换到左边;
  2. 每一轮循环可将最小值交换到最左边;
  3. 下一轮从之后的位置开始重复1,2 过程,直至完成整个数组。

算法实现

 

 

 

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值