冒泡排序,选择排序,qsort快排,详细解说:

最近不少朋友可能被排序的问题所困扰,特别是我们常见的两大基本排序问题:冒泡排序,选择排序;在这里我将会和简单介绍一下冒泡排序和选择排序的使用,然后详细讲解一下qsort快速排序;

1.冒泡排序

2.选择排序

3.qsort快排

(1)qsort函数的函数库及其所调用参数,返回类型

(2)各个参数的解释:

void *base

 size_t num

 size_t width

int (__cdecl *compare )(const void *elem1, const void *elem2 )

话不多说,进入正题:

1,冒泡排序:

我们先举个例子:输入5名学生成绩存放一维数组,用冒泡排序从小到大,输出原始成绩和排序后成绩。(从小到大输出)

 #include<stdio.h>
#define N 5
void Bubblesort(int arr[], int sz)
{
    int i = 0;
    int j = 0;
    for (i = 0; i < sz - 1; i++)
    {
        for (j = 0; j < sz - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
    printf("排序后成绩:\n");
    for (i = 0; i < sz; i++)
        printf("%d  ", arr[i]);
    printf("\n");
}

int main()
{
    int i;
    int arr[N];
    printf("请输入%d名学生成绩:\n",N);
    for (i = 0; i < N; i++)
    {
        scanf("%d", &arr[i]);
    }
    printf("原始成绩:\n");
    for (i = 0; i < N; i++)printf("%d ", arr[i]); printf("\n");
    int sz = sizeof(arr) / sizeof(arr[0]);
    Bubblesort(arr, sz);
    return 0;
}

即有5个元素的数组我们假设为56,65,67,76,78,冒泡排序就是类似于两两比较,定义两个循环变量i(控制比较的趟数),j(一趟比较的次数)进入冒泡排序(因为每一趟我们可以选择一个最大的数,最后两个数比较时,一个确定为最大,那另一个也就自然而然地确定了,所以我们需要比较9趟),一开始进入第一趟(i=0),第一次arr[0]与arr[1]比较,如果前者大于后者,则两者互换位置,否则,两者不互换;比较后,进入第二次比较,由于每次比较结束后j都会自增,所以第二次为arr[1]与arr[2]比较,如此往复;我们第一趟比较完后会在最后选择出最大值78。进入第二趟(i=1)因为上一躺我们已经选择出最大值78,所以第二趟比较的时候就不用再与最后的那个78参与比较了(因为78已经是最大值再次比较也不会改变他的位置,多余的比较只会影响计算机的运行速度),所以第二趟我们需要比较的次数就是sz-i-1(sz总元素个数,sz-1比较的第一躺两两比较的次数;sz-1-i第i行比较的次数(eg:第一行我们需要比较4次)),然后第二行两两比较如此往复......我们就实现了冒泡排序,截下来我们只要将数组的值用一个循环输出就ok了。

2,选择法:斯~(本人不太喜欢选择法)

同样的,我们回到上一个例子:输入5名学生成绩存放一维数组,用冒泡排序从小到大,输出原始成绩和排序后成绩。(从小到大输出)

#include<stdio.h>
#define N 5
void Selectsort(int arr[])
{
    int i, j,k;
    for (i = 0; i < N-1; i++)
    {
        k = i;
        for (j = i+1; j <N; j++)
        {
            if (arr[k]> arr[j])k=j;//选择最小的数
        }
        int tmp = arr[i];
        arr[i] = arr[k];
        arr[k] = tmp;//将最小的数于前面的数交换
    }
printf("排序后成绩:\n");
for (i = 0; i <N; i++)
 printf("%d ", arr[i]); 
 printf("\n");
}
int main()
{
    int i;
    int arr[N];
    printf("请输入%d名学生成绩:\n", N);
    for (i = 0; i < N; i++)
    {
        scanf("%d", &arr[i]);
    }
printf("原始成绩:\n");
for (i = 0; i < N; i++)
  printf("%d ", arr[i]);
  printf("\n");
 Selectsort(arr);
    return 0;
}

选择法最主要是先在数组元素中选择最小的元素,将其与第一个元素互换一下位置。第一次比较我们要比较四次,我们先保留i原数据的值,定义一个k,k赋值为i,让arr[k]与arr[j]比较,选择出最小的值56再与arr[0]互换位置。然后第二次我们的选择范围会缩短(减少计算机运算时间,因为arr[0]我们已经确定为最小值,所以再次比较位置也不会变化)然后我们除去56再选择最小的值65与arr[1]互换位置,如此往复...便完成选择。我们只需在最后输出即可。(个人观点(可忽略):对我个人,这个算法我几乎不用,但考虑到各位朋友可能会有些疑惑,我只好被迫加班咯)

怎么说呢,最近各位都在为冒泡和选择排序的过程太繁琐而苦恼着,我就和大家介绍一下另一种函数(不知道朋友们的老师讲不讲,反正我的老师目前没讲)好了,开始吧!

 

 (1)qsort(Quick Sort)即快速排序;我们所谓的冒泡排序,选择排序一般适用于数字之间的比较未免有些局限,而我们这里的qsort不仅可以是数字,字符串,结构体都可以用qsort进行比较,该函数返回类型为空,即不需要返回值,当我们使用参数时我们需要引用函数库stdlib即#include<stdlib.h>即可;

(2)我们看看数里面的参数:

第一个参数为void*base即首元素地址,因为qsort函数比较的类型很多,所以上面显示的为void*类型,而当我们真正用的时候,我们需要将其改成我们的带比较元素类型;

第二个参数为 size_t num即我们待比较元素的个数,举个例子,如果我们的比较的是arr[5]那么这里填写的就是5,但习惯我们用sizeof求个数;

(3)第三个size_t  width元素宽度即每个元素的大小(单位:字节);类似的,我们也习惯用sizeof来求解;

(4)这也是大家困惑最多的地方,比较函数,在这里是比较函数的函数地址,该函数两个参数,都是void类型,因为每个类型都不太相同,所以我们需要有一个统一的标准即全部强制转化为char*,这就完美的体现了(3)的作用,可以完美的使指针指向下一个元素,当然这是qsort函数内部应该解决的,和我们使用者没有关系,我们只需要严格的按照规定输入即可;

 cmp函数有返回类型,为int(这个也是确定的,不能更改),这是我们严格按照模板输入的,我们用e1-e2计算cmp的返回值,当返回值<0,则e1在前,>0时,则e2在前;

所以关于上面的例题,我们有如下解法:

#include<stdio.h>
#include<stdlib.h>
#define N 10
int cmp(const void* e1, const void* e2)//比较函数
{
    int* a = (int*)e1;
    int*b = (int*)e2;
    return (*a - *b);
}
int main()
{
    int i = 0;
    int arr[N];
    printf("请输入%d个数字:\n",N);
    for (i = 0; i < N; i++)
        scanf("%d",&arr[i]);
    printf("原始成绩:\n");
    for (i = 0; i < N; i++)
        printf("%d ", arr[i]); printf("\n");
    qsort(arr,N, sizeof(arr[0]),cmp);//快排实现

        
    printf("排序后成绩:\n");//输出
    for (i = 0; i <N; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

 

 这就避免了冒泡排序与选择排序的繁琐,是一个值得学习的新函数,好啦,感兴趣大家可以多多研究,就这样咯,拜啦

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值