冒泡排序及qsort实现

冒泡排序的核心思想就是:两两相邻的元素进行比较。

假设有一个数组,它是:8 3 2 7 10 9 1 0 7 4

现在我们要通过两两对比的方式将其升序排列。

我们要先将第一个和第二个对比,如果第一个数较大的话就交换位置。也就是说我们首先要将8和3对比然后交换位置,现在我们的数组就变为了3 8 2 7 10 9 1 0 7 4.

现在我们将第二个和第三个对比,8要大于2,所以8和2交换位置,现在我们的数组就变为了3 2 8 7 10 9 1 0 7 4.(这里3比2大,但是我们会向下继续比较,也就不会再管3和2谁大谁小了)

也就是说,我们要先比较下标0和下标1的数字,然后比较下标1和2的数字,再之后是3与4  4与5  5与6  6与7 7与8 8与9 9与10 下标的数字依次进行比较。

因此,我们要通过循环的方式来进行这段代码

for (int j = 0; j < 10; j++)
{if(arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}
}

现在,我们继续分析,经过这轮比较,每次比较中较大的数都会向右移动一位,这轮比较结束后,最右边的数字一定是目前数字中最大的数字,但是中间9个数字的大小却无法确定,如果你不能理解的话,可重读一遍上面的红字。

现在我们可以得知,只经过一次循环遍历是无法让数组有序的,但是可以让数字的最后一个元素最大。那么,如果我们剔除掉最后一个数字,再遍历一遍这个数组,是否就可以让倒数第二个数字最大了呢?如此循环往复,当我们第九次遍历的时候,是不是就可以让倒数第二个是最大的了呢,那么,我们整个的数组就有序了!

好,那么我们来写一下代码。

	for (int i = 0; i < 10; i++){for (int j = 0; j < 10-i; j++)//每次都可以少比较一个数{if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}

现在我们实现了一个冒泡排序,但是如果我给的数字是1 2 3 4 5 6 7 8 9 10的话,用上面的代码再进行排序,还是要进行一轮又一轮的比较才可以,即便它并不需要交换。所以我们的这段代码还是有一定优化空间的。

怎么优化呢?  

数组如果一轮下来是不是就没有交换了呢?那么我们是不是可以定义一个变量来判断数组是否有序呢?说干就干!我们来写一下。

	for (int i = 0; i < 10; i++){int flag = 1;//flag来标志是否进行了交换for (int j = 0; j < 10-i; j++)//每次都可以少比较一个数{if (arr[j] > arr[j + 1]){flag = 0;//如果交换了就置为0int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}if (flag == 1)//没交换即有序,退出即可。break;}

现在我们来把他包装称为一个函数。 我们先来思考以下两个个问题

1.  如何在函数内部更改main函数中的数组内容--->传址调用

2.函数需要几个参数-->数组和数组长度

好,有了这些,我们就来真刀阔斧的大干一场。

void bubble_sort(int* arr, int sz)
{for (int i = 0; i < sz-1; i++){int flag = 1;for (int j = 0; j < sz-1- i; j++)//每次都可以少比较一个数{if (arr[j] > arr[j + 1]){flag = 0;int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}if (flag == 1)break;}
}
int main()
{int arr[] = { 8,3,2,7,10,9,1,0,7,4};int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);for (int i= 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

现在我们就完成了一次冒泡排序。 下面我们来介绍下qsort函数。

qsort函数是C标准库中提供的一个用于排序的函数。

qsort函数的原型如下

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

qsort 函数的第一个参数 base 是需要排序的数组的起始地址,它可以是一个指向数组首元素的指针。

nmemb 是数组中元素的个数。

size 是每个元素的大小,以字节为单位。

compar 是一个函数指针,它指向一个比较函数,这个函数在后续判断了我们是升序排列还是降序排列。函数写法如下:

int cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}

现在我们来实践一下这个函数。

#include <stdio.h>
#include <stdlib.h>
int cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
int main()
{int arr[] = { 8,3,2,7,10,9,1,0,7,4 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

那么现在我们来写一下这个函数叭!

我会以注释的形式解释代码细节,请大家研读代码。

//交换函数
void swap(void* p1, void* p2, int size)//size是元素的大小
{int i = 0;for (i = 0; i < size; i++){//由于我们的这个函数要能够交换全部类型的元素//所以我们强转为char*类型的,一个地址一个地址的交换//是多大字节的类型,我们就每次交换多少个字节的地址内容。char tmp = *((char*)p1 + i);*((char*)p1 + i) = *((char*)p2 + i);*((char*)p2 + i) = tmp;}
}
//qsort主体
void bubble_qsort(void* base, int count, int size, int(*cmp)(void*, void*))
{int i = 0;int j = 0;//冒泡排序for (i=0; i < count - 1; i++){for (j=0; j < count - i - 1; j++){     //如果比较函数cmp大于0,则交换位置。//当然也可以cmp小于0,交换位置。//通过这个的改变来改变升降序.if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){    swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}
int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };int i = 0;bubble_qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), cmp);for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794752.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 ---- 慕尚花坊 订单列表

订单列表 本章节为课堂作业 01. 封装订单列表接口 API 思路分析&#xff1a; 为了方便后续进行商品管理模块的开发&#xff0c;我们在这一节将商品管理所有的接口封装成接口 API 函数 落地代码&#xff1a; ➡️ api/orderpay.js /*** description 获取订单列表* returns …

MongoDB聚合运算符:$maxN

文章目录 语法使用空和缺失值的处理 m a x N 和 maxN和 maxN和topN关于窗口功能和聚合表达式的支持关于内存的限制 举例找出一个项目中前三名的得分查找多个比赛项目中得分最高的三个基于$group分组的Key计算n $maxN聚合运算符用于返回聚合分组中最大的n个元素&#xff0c;如果…

160 Linux C++ 通讯架构实战14,epoll 反应堆模型

到这里&#xff0c;我们需要整理一下之前学习的epoll模型&#xff0c;并根据之前的epoll模型&#xff0c;提出弊端&#xff0c;进而整理epoll反应堆模型&#xff0c;进一步深刻理解&#xff0c;这是因为epoll实在是太重要了。 复习之前的epoll的整体流程以及思路。 参考之前写…

CSS - 你实现过0.5px的线吗

难度级别:中级及以上 提问概率:75% 我们知道在网页显示或是网页打印中,像素已经是最小单位了,但在很多时候,即便是最小的1像素,精度却不足以呈现所需的线条精度和细节。因此,为了在网页显示和网页打印中呈现更加细致的线条,为了在视觉…

Prometheus+grafana环境搭建Nginx(docker+二进制两种方式安装)(六)

由于所有组件写一篇幅过长&#xff0c;所以每个组件分一篇方便查看&#xff0c;前五篇链接如下 Prometheusgrafana环境搭建方法及流程两种方式(docker和源码包)(一)-CSDN博客 Prometheusgrafana环境搭建rabbitmq(docker二进制两种方式安装)(二)-CSDN博客 Prometheusgrafana环…

自动驾驶涉及相关的技术

当科幻走进现实&#xff0c;当影视照进生活&#xff0c;无数次憧憬的自动驾驶&#xff0c;正在慢慢的梦想成真。小时候天马星空的想象&#xff0c;现在正悄无声息的改变着我们的生活。随着汽车电动化进程的加快&#xff0c;自动驾驶技术映入眼帘&#xff0c;很多人可能感觉遥不…

逐步学习Go-sync.Once(只执行一次)Exactly Once

sync.Once简介 sync.Once 是一个会执行且仅执行一次动作的对象。该对象在第一次使用后不能再被复制。 在 Go 内存模型的术语中&#xff0c;sync.Once 的 Do 方法中的函数 f 返回的操作&#xff0c;相对于任何对 once.Do(f) 的调用返回的操作&#xff0c;都具有“同步优先”的…

Jupyter Notebook安装使用(一)

1. 简介 Jupyter Notebook 是一个非常强大的工具&#xff0c;它允许用户创建和共享包含实时代码、方程式、可视化和叙事文本的文档。这种工具特别适合数据清理和转换、数值模拟、统计建模、数据可视化、机器学习等多种应用领域。 2. 安装Jupyter Notebook 2.1. 使用 Anaconda…

Java面试题:请解释Java中的多线程编程?

Java中的多线程编程允许 concurrently 执行多个线程&#xff0c;从而可以同时执行多个任务&#xff0c;提高程序的效率和响应性。在Java中&#xff0c;线程可以通过以下两种主要方式来实现&#xff1a; 继承 Thread 类实现 Runnable 接口 继承 Thread 类 class MyThread ext…

Gson的用法

1. 导入依赖 <dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.6</version> </dependency> 2. 使用Gson进行解析 2.1 Gson解析普通对象 package com.jiang.partnetbackend.…

利用Idea实现Ajax登录(maven工程)

一、新建一个maven工程&#xff08;不会建的小伙伴可以参考Idea引入maven工程依赖(保姆级)-CSDN博客&#xff09;&#xff0c;工程目录如图 ​​​​​​​ js文件可以上up网盘提取 链接&#xff1a;https://pan.baidu.com/s/1yOFtiZBWGJY64fa2tM9CYg?pwd5555 提取码&…

Chatgpt掘金之旅—有爱AI商业实战篇|专业博客|(六)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业博客领域有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。随着AI技…

ABBYY FineReader15免费电脑OCR图片文字识别软件

产品介绍&#xff1a;ABBYY FineReader 15 OCR图片文字识别软件 ABBYY FineReader 15是一款光学字符识别&#xff08;OCR&#xff09;软件&#xff0c;专门设计用于将扫描的文档、图像和照片中的文本转换成可编辑和可搜索的格式。这款软件利用先进的OCR技术&#xff0c;能够识别…

递归算法解读

递归&#xff08;Recursion&#xff09;是计算机科学中的一个重要概念&#xff0c;它指的是一个函数&#xff08;或过程&#xff09;在其定义中直接或间接地调用自身。递归函数通过把问题分解为更小的相似子问题来解决原问题&#xff0c;这些更小的子问题也使用相同的解决方案&…

微信小程序短链接工具推荐

现在微信小程序大行其道&#xff0c;但工作中大部分人选择了短链接的方式来推广微信小程序&#xff0c;那么微信小程序短链接工具哪个好?今天就分享一篇从网上看到的关于《微信小程序短链接工具推荐》文&#xff0c;作者是souki&#xff0c;一起来看看吧! 一、缩链 1、生成方…

MongoDB聚合运算符:$maxN(用于数组)

文章目录 语法使用举例 $maxN聚合运算符返回数组中最大的n个值。 语法 { $maxN: { n: <expression>, input: <expression> } }参数说明&#xff1a; n&#xff1a;正整数表达式&#xff0c;用于指定返回数组元素的数量。input&#xff1a;可以解析为数组的表达式…

Memcached 教程之 PHP 连接 Memcached 服务(十)

PHP 连接 Memcached 服务 在前面章节中我们已经介绍了如何安装 Memcached 服务&#xff0c;接下来我们为大家介绍 PHP 如何使用 Memcached 服务。 PHP Memcache 扩展安装 PHP Memcache 扩展包下载地址&#xff1a;PECL :: Package :: memcache&#xff0c;你可以下载最新稳定…

【VASP学习】在Ubuntu系统安装vasp.5.4.4的全过程(包括VASP官方学习资料、安装过程中相关编辑器的配置、VASP的编译及VASP的测试)

在Ubuntu系统安装vasp.5.4.4的全过程 VASP的简介与相关学习资料安装前的准备工作及说明安装过程intel编译器的安装VASP的编译VASP的测试 参考来源 VASP的简介与相关学习资料 VASP(Vienna Ab initio Simulation Package)是基于第一性原理对原子尺度的材料进行模拟计算的软件。比…

【Linux】线程概念及线程互斥

目录 线程概念 线程优点 线程缺点 线程异常 线程系统编程接口 线程创建及终止 线程等待 使用线程系统接口封装一个小型的C线程库并实现一个抢票逻辑 线程互斥 互斥量的接口 线程互斥实现原理 使用系统加锁接口封装LockGuard 实现自动化加锁 线程安全和可重入函数 …

css:img引入svg后修改颜色

<img class"group-icon" :class"group.opened ? group-icon-active : ":src"require(/assets/icon/ group.icon .svg)" /> // 默认样式 .group-icon {width: 16px;height: 16px;position: relative;left: -1000px;filter: drop-shadow…