【算法】--- 几分钟了解直接选择排序(排序中最简单的排序)+快排(解决一切的优质算法)(中)

news/2024/10/17 20:19:55/

文章目录

  • 前言
  • 🌟一、常见的排序算法:
  • 🌟二、选择排序---直接选择排序:
    • 🌏2.1.1 基本思想:
    • 🌏2.1.2 直接选择排序:
    • 🌏2.1.3 直接选择排序的特性总结:
    • 🌏2.1.4 思路:
    • 🌏2.1.5 代码:
    • 🌏2.1.6 注意易错点:
  • 🌟三、交换排序---快速排序(上):
    • 🌏3.1.1 基本思想:
    • 🌏3.1.2 快速排序
      • 💫3.1.2.1 第一种---挖坑填补法:
        • 📒思路:
        • 📒代码:
        • 📒流程图:
        • 📒时间复杂度:
          • 🔑最好的情况:接近二分
          • 🔑最坏的情况:有序
        • 📒解决方法:三数取中---解决了快排中最坏的情况
          • 🔑代码:
        • 📒补充知识点:>>1与/2的关系
        • 📒小区间优化:
          • 🔑代码:
  • 😽总结


前言

👧个人主页:@小沈熬夜秃头中୧⍤⃝❅
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:算法
🔑本章内容:选择排序中的直接选择排序和交换排序中的快速排序
送给各位💌:你被黑暗敲打恰恰说明你是光明本身
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


提示:以下是本篇文章正文内容,下面案例可供参考

🌟一、常见的排序算法:

前面的插入排序可以回顾【算法】— 几分钟带你走进排序算法大门(上)
选择排序中的堆排序可以回顾【数据结构】—堆排序+TOP-K问题(了解游戏排行底层原理)
交换排序中的冒泡排序可以回顾C-指针的进阶(下)+qsort库函数
所以本章讲解选择排序中的直接选择排序和交换排序中的快速排序请添加图片描述

🌟二、选择排序—直接选择排序:

🌏2.1.1 基本思想:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

🌏2.1.2 直接选择排序:

  • 在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素
  • 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
  • 在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

🌏2.1.3 直接选择排序的特性总结:

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

🌏2.1.4 思路:

遍历比较选取一个最大的数,一个最小的数,将最小的数和开始位置值交换,最大的数和末尾位置值交换。

🌏2.1.5 代码:

#include<stdio.h>
void Swap(int*  p1, int* p2)
{int* tmp = *p1;*p1 = *p2;*p2 = tmp;
}
void SelectSort(int* a, int n)
{int begin = 0;int end = n - 1;while (begin < end){int mini = begin, maxi = begin;for (int i = begin; i <= end; i++){if (a[i] < a[mini]){mini = i;}if (a[i] > a[maxi]){maxi = i;}}Swap(&a[begin],& a[mini]);if (begin == maxi){maxi = mini;}Swap(&a[maxi],& a[end]);begin++;end--;}
}
int main()
{int a[] = { 9,5,1,7,4,2,6,8![请添加图片描述](https://img-blog.csdnimg.cn/98bf39b9ed01460b83de60cbbe6f3a74.png)
,0,8 };int n = sizeof(a)/sizeof(a[0]);SelectSort(a, n);for (int i = 0; i < n; i++){printf("%d ", a[i]);}return 0;
}

🌏2.1.6 注意易错点:

这一部分是必须要加上的,不然会出现一个bug,当交换开始位置值与最小值之后,要想一下若最大值就是开始位置值,再交换最大值和末尾值那最大值已经和最小值位置交换了不懂可以看下图:

		Swap(&a[begin],& a[mini]);if (begin == maxi){maxi = mini;}Swap(&a[maxi],& a[end]);begin++;end--;

请添加图片描述

🌟三、交换排序—快速排序(上):

🌏3.1.1 基本思想:

所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

🌏3.1.2 快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

💫3.1.2.1 第一种—挖坑填补法:

📒思路:

快速排序算法是基于分治策略的另一个排序算法。

该方法的基本思想是
1.先从数列中取出一个数作为基准数,记为key。
2.分区过程,将小于key的数全放到它的左边大于key的数全放到它的右边

📒代码:

#include<stdio.h>
void QuickSort(int* a,int left ,int  right)
{//剩下一个数或者没有数就达到了排序就不用排了if (left >= right){return;}int begin = left, end = right;int pivot = begin;int key = a[begin];while (begin < end){//右边找小,放到左边while (begin < end && a[end]>=key){end--;}//找到放在左边的坑里a[pivot] = a[end];pivot = end;//左边找小,放到右边while (begin < end && a[begin] <= key){begin++;}a[pivot] = a[begin];//找到放在右边的坑里pivot = begin;}//相遇了pivot = begin;a[pivot] = key;//分治策略,分区间将key左边和右边分别再次找关键key然后再次左小右大//直到剩下一个数或者没有数就达到了排序的目的QuickSort(a, left, pivot - 1);//注意传递的区间QuickSort(a, pivot +1,right);//注意传递的区间
}
int main()
{int a[] = { 9,5,1,7,4,2,6,3,0,8 };int n = sizeof(a) / sizeof(a[0]);QuickSort(a, 0,n-1);for (int i = 0; i < n; i++){printf("%d ", a[i]);}return 0;
}

📒流程图:

然后再分为左区间,右区间然后再从左区间中找关键数字再次进行下图这种流程,右区间同理就类似二叉树在这里插入图片描述
在这里插入图片描述

📒时间复杂度:

🔑最好的情况:接近二分

快排最好的情况就是二分(选取的key值正确位置刚好接近中间位置):每一次将一个数排到正确位置,分治算法就相当于一个完全二叉树高度为logN,且每一次时间复杂度O(N),所以总共时间复杂度是O(NlogN)*

请添加图片描述

🔑最坏的情况:有序

快排最坏情况就是有序:当有序时选取最左边(最右边)的数那么都小于(大于)其他数,就会出现左边(右边)没有要排的数,这样每一次都只排一个不像上面的情况类似一个二叉树

请添加图片描述

📒解决方法:三数取中—解决了快排中最坏的情况

🔑代码:
#include<stdio.h>void Swap(int*  p1, int* p2)
{int* tmp = *p1;*p1 = *p2;*p2 = tmp;
}int GetMidIndex(int* a, int left, int right)
{int mid = (left + right) >> 1;if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right]){return left;}else{return right;}}else//a[left]>a[mid]{if (a[mid] > a[right]){return mid;}else if (a[left] < a[right]){return left;}else{return right;}}
}
void QuickSort(int* a,int left ,int  right)
{//剩下一个数或者没有数就达到了排序就不用排了if (left >= right){return;}int index = GetMidIndex(a, left, right);Swap(&a[left], &a[index]);int begin = left, end = right;int pivot = begin;int key = a[begin];while (begin < end){//右边找小,放到左边while (begin < end && a[end]>=key){end--;}//找到放在左边的坑里a[pivot] = a[end];pivot = end;//左边找小,放到右边while (begin < end && a[begin] <= key){begin++;}a[pivot] = a[begin];//找到放在右边的坑里pivot = begin;}//相遇了pivot = begin;a[pivot] = key;//分治策略,分区间将key左边和右边分别再次找关键key然后再次左小右大//直到剩下一个数或者没有数就达到了排序的目的QuickSort(a, left, pivot - 1);QuickSort(a, pivot +1,right);
}
int main()
{//int a[] = { 0.1,2,3,4,5,6,7,8,9 };int a[] = { 9,5,1,7,4,2,6,3,0,8 };int n = sizeof(a) / sizeof(a[0]);QuickSort(a, 0,n-1);for (int i = 0; i < n; i++){printf("%d ", a[i]);}return 0;
}

📒补充知识点:>>1与/2的关系

  • n为非负数时,>> 1和/ 2的结果是一样的
  • n为负数且还是偶数时,>> 1和/ 2的结果是一样的
  • n为负数且还是奇数时,>> 1和/ 2的结果是不一样的

📒小区间优化:

🔑代码:

当每次调用越到最后递归调用越多,所以可以将最后几层递归调用消除掉,越到最后所排序的区间越小所以采用直接插入排序接可以了
对于直接插入排序可以回顾【算法】— 几分钟带你走进排序算法大门(上)

if (pivot - 1 - left > 10){QuickSort(a, left, pivot - 1);}else{InsertSort(a + left, pivot - 1 - left + 1);}if (right-(pivot+1) > 10){QuickSort(a, pivot + 1, right);}else{InsertSort(a + pivot+1, right-(pivot+1) + 1);}

😽总结

请添加图片描述
😽Ending,今天的直接选择排序+快排(中)的内容就到此结束啦~,如果后续想了解更多,就请关注我吧,一键三连哦 ~


http://www.ppmy.cn/news/248353.html

相关文章

SpringBoot+MyBatisplus搭建校园新闻平台——已开源

概述 开发背景 校园新闻平台是以新闻宣传机构的在线信息发布需求为基础&#xff0c;随着数字化和信息化的快速发展&#xff0c;校园新闻在校园内的传播和沟通中变得越来越重要。学校需要一个有效的管理系统来整合、发布和传播校园新闻&#xff0c;以满足师生、校友和其他利益…

Java的引用

一、概述 其实java有4种引用&#xff0c;4种可分为强、软、弱、虚。我们将从这四个方面入手进行介绍。 二、强引用 首先看到我们有一个类叫M&#xff0c;在这个类里我重写了一个方法叫finalize()&#xff0c;我们可以看到这个方法是已经被废弃的方法&#xff0c;为什么要重写…

北大教授一年时间制作的Java300集课程,我免费分享给你~

Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表&#xff0c;极好地实现了面向对象理论&#xff0…

达内java面试题集_达内java面试题

JAVA面试题-COREJAVA部分1&#xff0e;在main(String[] args)方法内是否可以调用一个非静态方法&#xff1f;答案&#xff1a;不能2&#xff0e;同一个文件里是否可以有两个public类&#xff1f;答案&#xff1a;不能3&#xff0e;方法名是否可以与构造器的名字相同&#xff1f…

java cef 崩溃,xCrash异常补抓分析-Java奔溃

近来看了一些异常补抓相关资料&#xff0c;正好补一下相应的操作&#xff0c;发现爱奇艺的一个Xcrash的异常补抓框架 文章分为三部分&#xff0c;分别是Java奔溃&#xff0c;卡顿补抓&#xff0c;以及Native崩溃。 可以看一下基本架构的全貌 这一节是Java崩溃的说明 基本初始化…

没有容器Java怎么不停止_java – Maven Cargo不会停止容器

我有一个maven项目,我想使用Cargo-Maven-Plugin(1.1.1)启动和停止tomcat服务器来运行集成测试. org.codehaus.cargo cargo-maven2-plugin 1.1.1 start-container pre-integration-test start stop-container post-integration-test stop installed tomcat6x http://archive.apa…

java script 调用c_java script中的四种函数调用

撰写此文源于最近在看Douglas Crockford的’JavaScript:The Good Parts’中文译本《Javascript语言精粹》时&#xff0c;发现一些自己不知道或者没有一下子理解的东西&#xff0c;拿出来细细研究并记录一下。 函数被作为很重要的一部分在书中做了详细的介绍和举例。感觉函数的四…

java日期类型_Java 基础【12】 日期类型

java api中日期类型的继承关系 java.lang.Object --java.util.Date --java.sql.Date --java.sql.Time --java.sql.Timestamp 1. java.util.Date表示特定的瞬间&#xff0c;精确到了毫秒 两个构造函数(别的过期了的我就不说了) Date() Date(long date) 主要方法》》 boolean a…