排序算法探究

1、什么是排序

排序就是将一串数据按照大小顺序重新排列

2、为什么需要排序

数据处理中经常用到的一种算法。

3、为什么有这么多的排序算法

一种新算法的提出,必定是为了解决某种算法在某方面的不足。以下表格简要介绍了几种排序算法的性能。
排序算法性能比较

4、几种排序算法详解

本次代码测试使用C语音编写,其他语言亦可。

1、冒泡排序

冒泡排序顾名思义就是向吐泡泡一样,一次将一个最大数或者最小数排到数组的末尾,一次遍历下来就会找出一个最大/最小的数,然后接着遍历。如下动图很好的解释了这一排序算法。
冒泡排序

分析得知:
1、比较两个数据,如果右边的比左边大,则交换两个数据的位置。
2、一遍遍历下来,最大的数据就在数组的末尾,我们需要考虑使用双重for循环实现。
3、重复1、2步骤,直到遍历完整个数组。

C语音实现如下:

//冒泡排序
void bubble_Sort(int *array, int n)
{   
    int i = 0;
    int j = 0;
    int temp = 0;

    for(i = 0; i < n; i++)
    { 
        for(j = 1; j < n - i; j++) //最大的数已经放到数组的末尾了,所以不需要再比较了 因此 j < n-i
        {
            if(array[j - 1] > array[j])  //如果右边比左边大,就交换数据
            {
                 temp = array[j-1];
                 array[j - 1] = array[j];
                 array[j] = temp;
            }
        }
    }
}

我们实际测试一下:

int main()
{
    int i, num;
    int array[] = {333,3,276,6,9,18,25,11,21,144,488,908,325,1,10,25,9,18,39,11,98,45};
    num = sizeof(array)/sizeof(array[0]); //取数组长度
    printf("sizeof(array)/sizeof(array[0]) = %d \n", num);
    printf("原始数组是:\n");
    for(i = 0 ; i < num ; i++)
    {
        printf("%d ", array[i]);
    }
    printf("\n");

    bubble_Sort(array, num);
    //quick_sort(array, num);
    //insert_sort(array, num);
    //select_sort(array, num);
    printf("排序后的数组:\n");
    for(i = 0 ; i < num ; i++)
    {
        printf("%d ", array[i]);
    }
    printf("\n");

    return 0;
}

运行结果如下:

void@ubuntu:/mnt/hgfs/VMshare/code/c$ gcc sort.c 
void@ubuntu:/mnt/hgfs/VMshare/code/c$ ./a.out 
sizeof(array)/sizeof(array[0]) = 22 
原始数组是:
333 3 276 6 9 18 25 11 21 144 488 908 325 1 10 25 9 18 39 11 98 45 
排序后的数组:
1 3 6 9 9 10 11 11 18 18 21 25 25 39 45 98 144 276 325 333 488 908 
void@ubuntu:/mnt/hgfs/VMshare/code/c$ 
2、选择排序

选择排序的思想是,我们先遍历一遍数组,找到最小的那个,放在数组第一个位置,然后我们接着遍历数组,找到第二小的数据,放在数组第二个位置,然后接着遍历数组,找到第三小的那个数据…同样放一个动图来理解一下选择排序的实现过程:

选择排序算法

分析得知:
1、第一次遍历数组,找到最小的那个,和数组[0]交换。
2、第二次遍历数组,找到次小的那个,和数组[1]交换,一次类推。
3、同样可以使用双重for循环实现。

实现代码如下:

//选择排序
void select_sort(int array[], int n)  
{  
    int i, j, k , temp;

    for (i = 0; i< n; i++) 
    {   
        k = i ;
        for(j = i+1 ; j < n; j ++)
        {
            if(array[j] < array[k]) //array[k] 一直记录最小的那个数
            {
                k = j;
            }

        }
        if (k != i) //如果最小的那个数不是自己,则交换两个数的位置
        {
            temp = array[i];
            array[i] = array[k];
            array[k] = temp;
        }
    }  
} 

实际测试代码和结果同冒泡排序,不再赘述。

3、插入排序

插入排序的思想是,先将最开头的一个数据看成是有序的(因为只有一个数据,肯定是有序的嘛),然后依次查找后面的元素,按照顺序插入前面的有序表中。我们同样用一个动图来表示一下:
插入排序

分析得知:
1、先将第一个数据看成是有序的。
2、依次遍历后续的数据,插入前面的有序表中。
3、后面的数据遍历完成后,一个有序表就完成了。

我们用代码分析一下:

//插入排序
void insert_sort(int array[], int n)  
{  
    int i,j,temp;  
    for (i = 1; i < n; i++) //刚开始array[0]看做是一个有序表。 
    {  
        temp = array[i]; 
        //将后面数据依次插入前面的有序表。从有序表的末尾开始查找,因为我们取出来一个数据,末尾刚好空出来了。
        for (j = i - 1; j >= 0 && array[j] > temp; j--) 
        {  
            array[j+1] = array[j];  
        }
        //有些同学可能理解不了,array[j+1] = array[j]; 后面为啥还有一个:array[j+1] = temp; 
        //其实 我们for循环中有个j--,所以这里又j+1 两个含义是不同的,要仔细体会一下
        array[j+1] = temp;  
    }  
}

测试代码同上,不在赘述。

4、快速排序

快速排序算法是1962年提出的,至今已经过去半个多世纪了,任然敢称为快速排序算法,可见这个算法是很叼的。所以需要我们认真学习。

快速排序算法的思想是:我们先找一个基数,然后按照这个基数把比它小的放在他的左边,比它大的放在它的右边,遍历一次后,基数在数组的中间,左边是比他小的数,右边是比他大的数。然后在分开的两个数组中再用此方法继续分类,最后数据就按顺序排好了。是不是很神奇,也有点不好理解,没关系,我们先放一个动图来理解一下:

快速排序

我认为百度百科的解释简洁明了,直接套用。
快速排序详解

实现的代码如下:

//快速排序
void sort_swap(int *array, int left, int right)
{
    int temp;
    temp = array[left];
    array[left] = array[right];
    array[right] = temp;
}

//这个函数时快速排序算法实现的核心
unsigned int find_quick_sort_median(int *array, int left, int right)
{
    int temp = array[left];
    while (left < right)
    {
        while(left < right && temp <= array[right])
        {
            right --;
        }
        sort_swap(array, left, right);

        while(left < right && temp >= array[left])
        {
            left ++;
        }
        sort_swap(array, left, right);

    }

    return left;
}

void q_sort(int array[], int left, int right)
{
    int temp = 0;
    if(left < right)
    {
        //快速排序算法分而治之的思想
        temp = find_quick_sort_median(array, left, right);
        q_sort(array, 0, temp-1);
        q_sort(array, temp+1, right);
    }

}

void quick_sort(int *array, int n)
{
    q_sort(array, 0, n-1);
}

运行结果同上,不再赘述。

5、总结

各种排序算法的实现各不相同,在一些简单的场合下,我们使用哪种排序算法都无伤大雅。但是处理的数据非常多的时候,就要考虑使用哪种算法更优了。快速排序算法经过这么多年的发展,依然敢叫快速排序算法,可见:这种算法的速度确实是最快的。但是快速排序算法也有缺点:使用递归,如果数据很多的话,会消耗大量的内存。

现在我们选择排序算法,不是单独选择某一个,比如对于大数据量的排序,我们先使用快速排序算法,将数据分成几拨,然后使用选择排序或者插入排序。这样就兼顾各个算法的优缺点,达到排序性能最优。

排序算法需要研究的内容太多,不是几个经典排序算法就能解决的。后续有时间、有精力,再详细研究一下各个算法的优化以及几个排序算法的组合。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值