ZackSungy

导航

总结一下常用的排序,冒泡排序,选择排序,快速排序

最近学习了几种排序。

 

(一)冒泡排序:

 实现原理:

比如有一个数组 10,  43,  48,  1,  8,  3,  5,  7,  1,  -21

第一次的第一轮:10小于43,所以10和43不交换位置;

第一次的第二轮:43小于48,所以43和48不交换位置;

第一次的第三轮:48大于1,所以48和1交换位置;变成了  10,  43,  1,  48,  8,  3,  5,  7,  1,  -21

第一次的第四轮:48大于8,所以48和8交换位置;变成了  10,  43,  1,  8,  48,  3,  5,  7,  1,  -21

第一次的第五轮:48大于3,所以48和3交换位置;变成了  10,  43,  1,  8,  3,  48,  5,  7,  1,  -21

第一次的第六轮:48大于5,所以48和5交换位置;变成了  10,  43,  1,  8,  3,  5,  48,  7,  1,  -21

........

以此类推,直到变成了  10,  43,  1,  8,  3,  5,  7,  1,  -21,48。

为什么呢?因为48是该数组中最大的数,第一次就通过这个方法把48放到了数组的最后面,下次就不用再跟48比较了。

所以下一次就不用去跟最后的数比较了,因为最后的数是最大的数。

根据这个规则一直循环下去,经过数组中的数的数量减去1次,就完成了排序。

下面是根据c语言的代码(c中不允许在for循环中定义变量,除了c99标准):

#include<stdio.h>

int main()
{
    int A[10] = { 10,43,48,1,8,3,5,7,1,-21 }, t,i,j;
    for (i = 0; i < 10 - 1; i++)
    {
        for (j = 0; j < 10 - i - 1; j++) //因为后面j加1,所以先要减1 
        {
            if (A[j] > A[j + 1]) //前面的数与后面的数比较大小 
            {
                t = A[j];
                A[j] = A[j + 1];
                A[j + 1] = t;
            }
        }
    }
    for (i = 0; i < 10; i++)
    {
        printf("%d ", A[i]);
    }
    return 0;
}

 

总结:冒泡排序是一种用时间换空间的排序方法,时间复杂度为O(N^2)。

(二)选择排序:

 实现原理:

选择排序就是

将第一个数与他后面数中最小的数互换位置。

将第二个数与他后面数中最小的数互换位置。

将第三个数与他后面数中最小的数互换位置。

.......

直到将数组的数的数量减1的数与他后面数中最小的数互换位置。

选择排序代码(代码是用c++编译的,如果使用c的话就改一下头文件为#include<stdio.h>和for循环内的变量定义在外面):

#include<cstdio>

int main()
{
    int A[10] = { 10,43,48,1,8,3,5,7,1,-21 }, t, min;
    for (int i = 0; i<10 - 1; i++)
    {
        int index = i;//记录数的位置
        min = A[i];//记录数的大小
        for (int j = i + 1; j<10; j++)
            if (min>A[j])     //得到比他小的数,如果没有就是他自己
            {
                min = A[j];   //得到最小数的大小
                index = j;    //得到最小数的位置
            }
        t = A[i];             //交换位置,没有他自己,没有改变位置
        A[i] = min;
        A[index] = t;
    }


    for (int i = 0; i<10; i++)
        printf("%d ", A[i]);
    return 0;
}

 

 

总结:选择排序的平均时间复杂度为O(N^2)。

注:以上两种排序方法因为时间复杂度较大,所以现在很少使用。

 

(三)快速排序:

实现原理:

以下面代码为例:

将第一个数作为key值保存,也就是10。

然后从右边开始寻找,进入第一个循环,依次向左移,直到找到比key值小的数。

右边第一个数-21比10要小,所以退出第一个循环,第一个值为-21。数组变成  -21,  43,  48,  1,  8,  3,  5,  7,  1,  -21。

然后从左边开始寻找,进入第一个循环,依次向左移,直到找到比key值小的数。

左边第一个数10与key值10相等,继续循环。

左边第二个数43比10要大,所以退出第二个循环,数组变成  -21,  43,  48,  1,  8,  3,  5,  7,  1,  43。

因为左边和右边位置还不相同,所以重新进入第一个循环第一个循环(i<j的意义)。

.......

以此类推

一直到数组为   -21,  1,  7,  1,  8,  3,  5,  7,  48,  43。

退出循环。此时i等于j(位置相同)。

i和j在第二个7的位置(如果不懂可以在每次数组循环后打印一次数组查看数组顺序,和查看一下i和j的位置)。

然后第二个7的位置上的值为10。

此时10的左边的数一定小于10,10右边的数一定大于10。

然后左边的数和右边的数分别进入递归,根据这种思想方法去排序,直到完成排序退出递归。

代码如下:

#include<cstdio>
using namespace std;

void QSort(int left, int right, int *A)
{
    if (left > right)return;//直到数组中只有唯一一个数,退出递归。
    int i = left;
    int j = right;
    int key = A[left];
    while (i<j)
    {
        while (i<j&&key <= A[j])j--;//从右边开始,找到比key小的数。
        A[i] = A[j];
        while (i<j&&key >= A[i])i++;//从左边开始,找到比key大的数。
        A[j] = A[i];
    }
    A[i] = key;//重新获得key的值。
    QSort(left, i - 1, A);//排列左边的数。
    QSort(i + 1, right, A);//排列右边的数。
}

int main()
{
    int A[10] = { 10,43,48,1,8,3,5,7,1,-21 };

    QSort(0, 9, A);

    for (int i = 0; i<10; i++)
        printf("%d ", A[i]);
    return 0;
}

 

总结:快速排序的时间复杂度为O(N),相比于前两种排序的使用时间要少很多,在很多复杂的排序中经常用到。

 

**以上有什么错误还望指出,希望我们共同学习。**

 

posted on 2017-06-05 22:17  ZackSungy  阅读(264)  评论(0编辑  收藏  举报