一.冒泡排序

冒泡排序是一种常见的排序方式,它可以把数组元素有序或无序的数组进行重新排序,并使得数组中的元素从大到小或从小到大进行排序(就像泡泡一样)。

冒泡排序原理:

每次比较数组中的相邻的两个元素的值,将较小的元素排在较大的元素的前面,就可实现数组元素从小到大排序;每次将较大的元素排在较小的元素的前面,就可实现数组元素从大到小排序。

以数字1,2,7,3,9,6为例,使其从大到小排序

对上表进行分析:

第一次排序将最大的数字移动到第一第一元素[0]的位置,并将其它数字以次向后移动;第二次排序中,从第二个数字开始从剩余数字中挑选最大的数字,并将其移动到第二个位置,剩余数字依次向后移动;以此类推,可将数字1,2,7,3,9和6从大到小排列。

代码实现:

#include<stdio.h>int main()
{int arr[10] = { 0 };int i = 0, j = 0, tmp = 0;for (i = 0; i < 10; i++){scanf("%d", &arr[i]);//依次输入你想排列的数字}for (i = 9; i >= 1; i--){for (j = i; j >= 1; j--){if (arr[j] > arr[j - 1]){tmp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = tmp;}}}for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;return 0;
}

对上述代码进行分析:

我们可以看到总共有6个数字元素,单却只排序5次。在最后依次排序过程2与1交换了位置刚好满足从大到小排列,也就是说该数组你设置了n个元素那就要排序n -1次。

那依次排序中数组中的元素交换了多少次呢?

由图表可知,在第一次排序中,我们可以观察到【6,9】,【9,3】,【9,7】,【9,2】,【9,1】格一次总共是五次;在第二次排序中,因为我们已经知道9为最大值并且排在了[0]位置,所以9可以不用交换了,只需交换9后面的数字元素即可,这时总共交换了4次。以此类推可知第五次只需交换一次。由此可知,每次排序之后,数组元素需交换的次数都会减一。所以在代码实现中我套用了两层循环一层for(i=9;i>=1;i--)就是要排序的次数,另一层for(j=i;j>=1;j--)就是每次排序中需交换的次数。而j>=1这个判断条件是为了防止数组越界的。(因为如果j=0的话arr[j-1]就越界了)

二.qsort函数详解

qsort函数是C语言标准库中的一种库函数,它的作用就是快速排序,而要使用它的话就需要引用头文件#include<stdlib.h>。

qsort的函数原型:

void qsort (void* base,size_t num,size_t size,int (* compar) (const void*e1,const void*e2)

现在对qsort函数原型进行分析:

1.void qsort:

这个void代表qsort函数是一个无返回类型的函数。

2.void* base:

这个void*代表着是base的类型。base被官方解释为指向要排序的数组的第一个对象的指针,转换为空*。也就是说base,其实就是数组首元素的地址。

具体实现:int values[6]={40,10,100,90,20,25};

qosrt(values,6,sizeof(int),compare);

3.size_t num:

这个size_t代表着是num的类型(size_t其实就是unsigned int 无符号整型),在官方的解释中num是按基数指向数组中的元素数,也就是说num就是你传给qsort这个函数的数组中的元素个数

具体实现: qosrt(values,6,sizeof(int),compare);这个6就是num。

4.size_t size

size_t同上,size在官方的解释中就是数组中每个元素的大小(以字节为单位)。

具体实现: qosrt(values,6,sizeof(int),compare);这个sizeof(int)就是int类型的值在内存中占多少个字节,因为数组values就是int类型的数组。

5.int (*compare)(const void*e1,const void*e2)

现在对上式进行分析。这是一个返回值类型为整型的函数指针,其中compare函数的两个参数的类型为const void*。而在官方的解释中这是一个指向比较两个元素大小的函数指针。

在qsort函数中的compare函数的使用方式类似于strcmp函数,qsort函数主要是通过compare函数的返回值来判断传入compare函数的两个元素的值的大小关系。如果返回值小于零的话那么元素e1就小于e2;如果返回值等于零的话e1==e2;如果返回值大于零的话e1就大于e2。

也就是说compare函数就是一种比较方法,用来比较传入compare函数的两个值的大小的。

这个图片就是官方给出的解释。

综上,qosrt的使用就是这样的:

qsort(数组名,数组元素个数,数组每个元素的大小(以字节为单位),比较函数)

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>int compare(void* e1, void* e2)
{return (*(int*)e1 - *(int*)e2);//把e1,e2强制转换为(int*)类型的因为传到数组的元素就是int类型的。
}int main()
{int arr[10] = { 0 };for (int i = 0; i < 10; i++){scanf("%d", &arr[i]);}qsort(arr, 10, sizeof(arr[0]), compare);//总结就是 qsort(数组名,数组元素个数,数组每个元素的大小(以字节为单位),比较函数)for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

运行结果:

三.qosrt函数的模拟实现

通过观察qsort函数的代码实现以及函数原型,我们可以仿照出一个类似的函数,这个函数必须要具备qsort函数的所有功能。

我先设这个函数名称为bubble_sort,很多人可能会问,为什么我要把冒泡函数与qsort函数一起讲?等会你们就知道了。

我们既然要让bubble_sort实现qsort的功能那么在bubble_sort函数内部必然有一个排序语句来帮助bubble_sort这个函数正真实现快速排序,而冒泡排序法就是这个函数内部的的排序语句。但是qsort函数的模拟实现最主要也是最难的就是数组元素的交换,因为它涉及到了函数指针和强制类型转换,不多bb直接上代码然后解释一下具体怎么交换数组元素。

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>int compare(void* e1, void* e2)
{return (*(int*)e1 - *(int*)e2);
}
void bubble_sort(int* p, size_t num, size_t size, int(*compare)(void* e1, void* e2))
{int i = 0, j = 0;for (i = num - 1; i >= 1; i--){for (j = 0; j < i; j++){if (compare((char*)p+j*size,(char*)p+(j+1)*size) > 0){int x = 0;char tmp;for (x = 0; x < size; x++){tmp = *((char*)p + j * size+x);*((char*)p + j * size+x) = *((char*)p + (j + 1) * size+x);*((char*)p + (j + 1) * size+x) = tmp;}}}}
}
int main()
{int arr[10] = { 0 };for (int i = 0; i < 10; i++){scanf("%d", &arr[i]);}bubble_sort(arr, 10, sizeof(arr[0]), compare);for (int i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

为了使我们模拟实现的bubble_sort函数能够排序多种类型包括整型(int,short,long,long),字符型(char)以及实型也叫浮点型(float,double),所以我们需要把数组元素强制转换为char*类型。

在上述代码中我们可以看到compare((char*)p+j*size,(char*)p+(j+1)*size),这里传过去的的是(char*)p+j*size和(char*)p+(j+1)*size,在这里如果我们只传(char*)p是显然行不通的,因为p这个地址就是数组arr的首元素地址,因为我们需要交换数组里面的所有元素所以我们就要传两个相邻的数组元素,而这两个元素会随着循环次数增加而改变。如j=0是(char*)p+j*size实际上就是arr[0],(char*)p+(j+1)*size显然就是arr[1]了,而随着j增加传过去的元素也会改变。(其中size就是数组元素的大小,而(char*)p加了j*size,地址p就会向后移动j*size个字节,也就是arr[]的下标会移动加j)。

而*((char*)p+j*size+x)和*((char*)p+(j+1)*size+x)其实就是对(char*)p+j*size+x以及后者的解引用而言,这里值得注意的是x,为什么要加x?是因为p已经被强制类型转换成了char*型的所以我们为了交换数组元素就要一个字节一个字节的交换(char类型占内存是1个字节,int是4个字节)。而且这个加x就是使p向后位移x位。

ps:compar函数传过去的参数应该是两个指针。

冒泡排序和qsort函数详解以及如何模拟实现qsort函数相关推荐

  1. linux内核中的hook函数详解,linux内核中的hook函数详解

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

  2. Kotlin——高阶函数详解与标准的高阶函数使用

    一.高阶函数介绍 在介绍高阶函数之前,或许您先应该了解Kotlin中,基础函数的使用与定义.您可以参见Kotlin--初级篇(七):函数(方法)基础使用这边文章的用法. 在Kotlin中,高阶函数即指 ...

  3. python自定义函数详解_python基础教程之自定义函数介绍

    函数最重要的目的是方便我们重复使用相同的一段程序. 将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句. 函数的定义 首先,我们要定义一个函数, 以 ...

  4. python内置函数详解总结篇_Python内置函数详解——总结篇

    数学运算(7个) 类型转换(24个) 序列操作(8个) 对象操作(7个) 反射操作(8个) 变量操作(2个) 交互操作(2个) 文件操作(1个) 编译执行(4个) 装饰器(3个) 数学运算 abs:求 ...

  5. php mysql 操作函数_PHP操作mysql函数详解,mysql和php交互函数

    1. 建立和关闭连接1) mysql_connect() resource mysql_connect([string hostname [:port][:/path/to/socket][,stri ...

  6. python100个内置函数详解_Python 63个内置函数详解

    Python 内置函数最全汇总: 1 abs() 绝对值或复数的模 In [1]: abs(-6) Out[1]: 6 2 all() 接受一个迭代器,如果迭代器的所有元素都为真,那么返回True,否 ...

  7. reduce函数详解以及自己实现一个reduce函数

    开篇语: 一直以来都知道数组有一个reduce方法,可是在工作过程中很少用到,对其用法也不是很清晰,今天抽时间好好整理一下,希望加深记忆,以后在工作过程中做到手到擒来,得心应手. 1.概念 首先看一下 ...

  8. linux中 fopen函数,详解C语言中的fopen()函数和fdopen()函数

    C语言fopen()函数:打开一个文件并返回文件指针头文件: #include fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * ...

  9. 函数详解:包括库函数和自定义函数,函数的参数及调用,声明及定义,嵌套使用和链式访问

最新文章

  1. 第二节 线程启动、结束、创建线程多个方法、join()、detach()
  2. 【Android 逆向】selinux 进程保护 ( selinux 进程保护 | 宽容模式 Permissive | 强制模式 Enforcing )
  3. linux系统安装柯美打印机,柯尼卡美能达复印机中标麒麟系统驱动安装
  4. 一名即将大三的小伙子在疫情期间的思考与总结
  5. 异常处理python要求输入的为英文_python(异常处理)
  6. SAP Cloud for Customer的Calculated field字段
  7. html节点上下移动,关于前端:数组元素上下移动
  8. .net remoting 技术
  9. 3_python基础—运算符 2
  10. Linux删除安卓温控,RK平台关闭温度控制降频功能
  11. aop cache再讨论
  12. system.Exception:端口已被占用1080
  13. 荆棘鸟(The Thorn bird)
  14. K8s安装dashboard可视化界面
  15. 苹果官网价格乌龙1499元被标149 元
  16. 赋能合作伙伴,共建价值生态 | ZDNS产品及行业解决方案培训会圆满举行
  17. 关于win7 32bit连接win10共享打印机0x0000011b解决办法
  18. Android 获取系统语言
  19. #sora#celery笔记——call the task
  20. node.js+uniapp计算机毕业设计安卓移动LYQ电子商城APP(程序+APP+LW)

热门文章

  1. 用冒泡法对任意输入的10个数由小到da进行排序
  2. QMediaPlayer 打包解码器注意事项
  3. 2018年上海各区重点小学排名
  4. pd4ml中文乱码解决-手动添加字体文件
  5. 【北京迅为】i.MX6ULL终结者内核-Logo 修改使用文档生成 PPM 文件
  6. 字符与字符串的表示(ASCII字符,Unicode码,字符串)
  7. C#、python企业微信群机器人自动发送文件
  8. 我和 WebSocket 的那些事(一)
  9. s6 android 6.0,三星Android 6.0更新升级详细名单:只有国行S6 Edge(G9250)
  10. Windows 11 消费者版 (含家庭版 / 专业版 / 专业工作站 / 家庭单语言版)