数据结构的快速排序(c语言版)

一.快速排序的概念

        

1.快排的基本概念

快速排序是一种常用的排序算法,它是基于分治策略的一种高效排序算法。它的基本思想如下:

  1. 从数列中挑出一个元素作为基准(pivot)。
  2. 将所有小于基准值的元素放在基准前面,所有大于基准值的元素放在基准后面。这个过程称为分区(partition)操作。
  3. 递归地应用上述步骤到左右两个子数列上,直到各个子数列只有一个元素为止。

这样通过不断的分割和排序,就可以实现整个数列的排序。快速排序的时间复杂度平均情况下为O(nlogn),虽然在最坏情况下会退化为O(n^2),但在实际应用中往往是一种高效的排序算法。

2.快排的适用场景

  1. 大规模数据排序:快速排序的平均时间复杂度为O(nlogn),在处理大规模数据时比其他算法如冒泡排序、插入排序更加高效。

  2. 内存受限的环境:快速排序是一种就地排序算法,不需要额外的存储空间,这在内存受限的环境(如嵌入式系统)中更有优势。

  3. 数据较为随机分布:快速排序的性能最佳情况发生在数据较为随机分布的情况下。如果数据已经基本有序或完全逆序,则会退化为O(n^2)的时间复杂度。

  4. 需要频繁排序的场景:由于快速排序的实现相对简单,且不需要额外空间,因此在需要频繁进行排序的场景中更有优势,如动态维护一个有序集合。

  5. 并行计算环境:快速排序可以很好地并行化,利用多核处理器可以大幅提高排序效率,在并行计算环境中表现出色。

总的来说,对于大规模、内存受限、数据较为随机分布且需要频繁排序的场景,快速排序通常是一个很好的选择。但对于小规模数据集或数据已经基本有序的情况,其他简单排序算法可能会更加高效。

3.快排的优点

优点:

  1. 时间复杂度平均情况下为O(nlogn),是比较高效的排序算法。
  2. 算法简单,且可以就地排序,不需要额外的存储空间。
  3. 相比于归并排序,快速排序的递归调用次数较少。
  4. 在硬件条件受限的情况下(如嵌入式系统),快速排序的空间复杂度优势更加明显。

4.快排的缺点

缺点:

  1. 最坏情况下的时间复杂度为O(n^2),发生在输入数据已经有序或完全逆序的情况。
  2. 对于小规模数据集,其他简单排序算法如插入排序、冒泡排序效率可能会更高。
  3. 快速排序是不稳定的排序算法,即相等元素的相对位置可能会改变。
  4. 算法实现的难度略高于一些其他排序算法,需要掌握分区操作等技巧

二.快速排序的功能

  1. 就地排序:快速排序是一种原地排序算法,它不需要额外的存储空间来保存中间结果。这使它在空间利用率方面具有优势,特别适用于内存受限的环境。

  2. 时间复杂度:快速排序的平均时间复杂度为O(nlogn),这使它成为高效的排序算法之一。但在最坏情况下,如输入数据已经完全有序或逆序,时间复杂度会退化到O(n^2)。

  3. 分治策略:快速排序采用分治的思想,通过不断将数组划分为较小的子数组,然后对子数组进行排序,最终达到整个数组有序的目标。这种递归的方式使算法实现相对简单。

  4. 分区操作:快速排序的核心是分区操作。它会选择一个基准元素,将数组划分为两个子数组,一个包含小于基准的元素,另一个包含大于等于基准的元素。这个过程是快速排序的关键。

  5. 随机化:为了避免最坏情况下的时间复杂度,快速排序通常会随机选择基准元素。这样可以保证平均情况下的高效性。

  6. 并行化:快速排序可以很好地并行化。在分区操作时,左右两个子数组是相互独立的,可以同时进行排序。这在多核处理器环境中可以大幅提高排序效率。

  7. 适用范围广泛:快速排序可以排序各种数据类型,如整数、浮点数、字符串等。并且可以根据实际需求定制比较函数,满足不同场景的排序需求。

  8. 稳定性:快速排序是一种不稳定的排序算法,即相等元素的相对位置可能会改变。如果需要保持相等元素的相对顺序,可以考虑使用其他稳定的排序算法,如归并排序。

三.快速排序的代码实现

1.变量的交换

swap(int *a, int *b) 函数的实现非常简单,它使用一个临时变量 temp 来交换 a 和 b 的值。这是一种常见的交换两个变量值的方式。

void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}

2.划分元素

partition(int arr[], int low, int high) 函数的核心思想是选择最后一个元素作为基准(pivot),然后将数组划分为两部分:小于基准的元素在左边,大于等于基准的元素在右边。它使用一个指针 i 来记录小于基准的子数组的最后一个位置,然后遍历数组,将小于基准的元素交换到左边。最后,它将基准元素交换到正确的位置,并返回该位置。

int partition(int arr[], int low, int high) {int pivot = arr[high];  // 选择最后一个元素作为基准int i = (low - 1);      // 小于基准的子数组的最后一个位置for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);
}

3.快排的递归实现

quickSort(int arr[], int low, int high) 函数实现了快速排序的递归过程。它首先检查数组长度是否大于 1,如果是,则调用 partition() 函数来划分数组。然后,它递归地对左右两个子数组进行排序。这个过程会一直持续,直到每个子数组的长度为 1 或 0,此时排序完成。

void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}

4.main函数

main() 函数展示了如何使用快速排序算法对一个整数数组进行排序。它首先创建一个示例数组,然后调用 quickSort() 函数对数组进行排序。最后,它打印出排序后的数组。

int main() {int arr[] = {10, 7, 8, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);printf("Sorted array: ");for (int i = 0; i < n; i++)printf("%d ", arr[i]);printf("\n");return 0;
}

四.快速排序的源代码

  1. swap(int *a, int *b) 函数用于交换两个整数的值。

  2. partition(int arr[], int low, int high) 函数用于将数组划分为两个子数组。它选择最后一个元素作为基准,然后将小于基准的元素放在左边,大于等于基准的元素放在右边。该函数返回基准元素的最终位置。

  3. quickSort(int arr[], int low, int high) 函数是快速排序的主要实现。它首先检查数组长度是否大于 1,如果是,则调用 partition() 函数来划分数组。然后递归地对左右两个子数组进行排序。

  4. main() 函数展示了如何使用快速排序算法对一个整数数组进行排序。它首先创建一个示例数组,然后调用 quickSort() 函数对数组进行排序。最后,它打印出排序后的数组。

这个实现使用了最后一个元素作为基准,并采用原地排序的方式。你可以根据需要修改基准的选择方式,或者添加随机化来避免最坏情况下的时间复杂度。

#include <stdio.h>
#include <stdlib.h>void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int partition(int arr[], int low, int high) {int pivot = arr[high];  // 选择最后一个元素作为基准int i = (low - 1);      // 小于基准的子数组的最后一个位置for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);
}void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}int main() {int arr[] = {10, 7, 8, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);printf("Sorted array: ");for (int i = 0; i < n; i++)printf("%d ", arr[i]);printf("\n");return 0;
}

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

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

相关文章

微信小程序-页面导航

一、页面导航 页面导航指的是页面之间的相互跳转&#xff0c;例如&#xff1a;浏览器中实现页面导航的方式有如下两种&#xff1a; 1.<a>链接 2.location.href 二、小程序中实现页面导航的两种方式 1.声明式导航 在页面上声明一个<navigator>导航组件 通过点击…

AIGC微短剧轻量化制作

AIGC&#xff08;生成式AI&#xff09;和微短剧作为影视领域的发展趋势&#xff0c;热度持续不减。行业巨头纷纷涉足其中&#xff0c;头部公司也陆续宣布加入竞争。这一趋势带来了新一轮的资本狂欢。 事实上&#xff0c;无论是被视为未来发展的风向标&#xff0c;还是像只是一…

【核心动画-关键帧动画-CAKeyframeAnimation Objective-C语言】

一、接下来,我们来说这个关键帧动画, 1.我们把之前的基本动画,这一坨代码,备份到test1方法里边, 然后,开始说我们的关键帧动画,步骤都是一样的,都是三大步: // 关键帧动画 // 1.做什么动画 // 2.怎么做动画 // 3.对谁做动画 1)做什么动画 第一,我们现在要创建…

证件/文书类日期中文大写js/ts插件

说明 证件/文书类落款日期中文大写往往会将“零”写作“〇”&#xff0c;而数字依然使用简体“一二三”&#xff0c;而不是“壹贰叁”。 如下&#xff1a; 针对这一点&#xff0c;写了如下转换插件。 代码 function DateToUpperCase(date: Date new Date()) {const chStr …

【移动端】商场项目路由设计

1&#xff1a;路由设计配置&#xff1a; 一级路由配置 分析项目&#xff0c;设计路由&#xff0c;配置一级路由 一级路由&#xff1a;单个页面独立展示的&#xff0c;都是一级路由&#xff0c;例如&#xff1a;登录页面&#xff0c;首页架子&#xff0c;报错页面 二级路由&…

ADuM1201可使用π121U31间接替换π122U31直接替换

ADuM1201可使用π121U31间接替换π122U31直接替换 一般低速隔离通信150Kbps电路可使用π121U31&#xff0c;价格优势较大。速度快的有其它型号可达10M,200M,600M。 本文主要介绍ADUM1201,替换芯片π121U31简单资料请访问下行链接 只要0.74元的双通道数字隔离器&#xff0c;1T1…

【VSCode】快捷方式log去掉分号

文章目录 一、引入二、解决办法 一、引入 我们使用 log 快速生成的 console.log() 都是带分号的 但是我们的编程习惯都是不带分号&#xff0c;每次自动生成后还需要手动删掉分号&#xff0c;太麻烦了&#xff01; 那有没有办法能够生成的时候就不带分号呢&#xff1f;自然是有…

ubuntu 18.04 ros1学习

总结了一下&#xff0c;学习内容主要有&#xff1a; 1.ubuntu的基础命令 pwd: 获得当前路径 cd: 进入或者退出一个目录 ls:列举该文件夹下的所有文件名称 mv 移动一个文件到另一个目录中 cp 拷贝一个文件到另一个目录中 rm -r 删除文件 gedit sudo 给予管理员权限 sudo apt-…

开源硬件初识——Orange Pi AIpro(8T)

开源硬件初识——Orange Pi AIpro&#xff08;8T&#xff09; 大抵是因为缘&#xff0c;妙不可言地就有了这么一块儿新一代AI开发板&#xff0c;乐于接触新鲜玩意儿的小火苗噌一下就燃了起来。 还没等拿到硬件&#xff0c;就已经开始在Orange Pi AIpro 官网上查阅起资料&…

基于安卓的虫害识别软件设计--(1)模型训练与可视化

引言 简介&#xff1a;使用pytorch框架&#xff0c;从模型训练、模型部署完整地实现了一个基础的图像识别项目计算资源&#xff1a;使用的是Kaggle&#xff08;每周免费30h的GPU&#xff09; 1.创建名为“utils_1”的模块 模块中包含&#xff1a;训练和验证的加载器函数、训练…

如何使用Spring Cache优化后端接口?

Spring Cache是Spring框架提供的一种缓存抽象,它可以很方便地集成到应用程序中,用于提高接口的性能和响应速度。使用Spring Cache可以避免重复执行耗时的方法,并且还可以提供一个统一的缓存管理机制,简化缓存的配置和管理。 本文将详细介绍如何使用Spring Cache来优化接口,…

【前端】Mac安装node14教程

在macOS上安装Node.js版本14.x的步骤如下&#xff1a; 打开终端。 使用Node Version Manager (nvm)安装Node.js。如果你还没有安装nvm&#xff0c;可以使用以下命令安装&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 然后关…

基于NANO 9K 开发板加载PICORV32软核,并建立交叉编译环境

目录 0. 环境准备 1. 安装交叉编译器 2. 理解makefile工作机理 3. 熟悉示例程序的代码结构&#xff0c;理解软核代码的底层驱动原理 4. 熟悉烧录环节的工作机理&#xff0c; 建立下载环境 5. 编写例子blink&#xff0c; printf等&#xff0c; 加载运行 6. 后续任务 0.…

卷积网络迁移学习:实现思想与TensorFlow实践

摘要&#xff1a;迁移学习是一种利用已有知识来改善新任务学习性能的方法。 在深度学习中&#xff0c;迁移学习通过迁移卷积网络&#xff08;CNN&#xff09;的预训练权重&#xff0c;实现了在新领域或任务上的高效学习。 下面我将详细介绍迁移学习的概念、实现思想&#xff0c…

【成品设计】基于STM32单片机的饮水售卖机

基于STM32单片机的饮水售卖机 所需器件&#xff1a; STM32最小系统板。RFID&#xff1a;MFRC-522用于IC卡检测。OLED屏幕&#xff1a;用于显示当前水容量、系统状态等。水泵软管&#xff1a;用于抽水。水位传感器&#xff08;3个&#xff09;&#xff1a;用于分别标定&#x…

低代码赋能企业数字化转型:数百家软件公司的成功实践

本文转载于葡萄城公众号&#xff0c;原文链接&#xff1a;https://mp.weixin.qq.com/s/gN8Rq9TDmkMpCtNMMsBUXQ 导读 在当今的软件开发时代&#xff0c;以新技术助力企业数字化转型已经成为一个热门话题。如何快速适应技术变革&#xff0c;构建符合时代需求的技术能力和业务模…

【STM32F103】HC-SR04超声波测距

【STM32F103】HC-SR04超声波测距 一、HC-SR041、工作原理2、其他参数及时序图 二、代码编写思路三、HAL配置四、代码实现五、实验结果 前言 本次实验主要实现用stm32f103HC-SR04实现超声波测距&#xff0c;将测距数值通过串口上传到上位机串口助手 一、HC-SR04 1、工作原理 (…

【Unity知识点详解】Addressables的资源加载

今天来简单介绍一下Addressables&#xff0c;并介绍一下如何通过AssetName加载单个资源、如何通过Label加载多个资源、以及如何通过List<string>加载多个资源。由于Addressables的资源加载均为异步加载&#xff0c;所以今天给大家介绍如何使用StartCoroutine、如何使用As…

计算机算法中的数字表示法——浮点数

目录 1.前言2.浮点数的形式3.举例说明4.浮点数四则运算 微信公众号含更多FPGA相关源码&#xff1a; 1.前言 前面讲了定点表示法&#xff0c;定点表示法有一个主要的限制&#xff0c;那就是它不能有效地表示非常大或非常小的数&#xff0c;因为小数点的位置是固定的。为了解决这…

ios:文本框默认的copy、past改成中文复制粘贴

问题 ios 开发&#xff0c;对于输入框的一些默认文案展示&#xff0c;如复制粘贴是英文的&#xff0c;那么如何改为中文的呢 解决 按照路径找到这个文件 ios/项目/Info.plist&#xff0c;增加 <key>CFBundleAllowMixedLocalizations</key> <true/> <…