常用排序算法详解

  • 1.冒泡排序
    • 原理
    • 示例
    • 代码实现
  • 2.快速排序
    • 原理
    • 示例
    • 代码实现
  • 3.插入排序
    • 原理
    • 示例
    • 代码实现
  • 4.希尔排序
    • 原理
    • 示例
    • 代码实现
  • 5.选择排序
    • 原理
    • 示例
    • 代码实现
  • 6.堆排序
    • 原理
    • 示例
    • 代码实现
  • 7.归并排序
    • 原理
    • 示例
    • 代码实现

本文讲述了常见的排序算法的执行过程,有详细实现过程举例

1.冒泡排序

原理

冒泡排序是指不断的遍历数组,比较相邻两个数的大小,如果顺序不对就将其掉换位置,直到所有的数据位置都正确

示例

原始数组 :[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]

操作次数排序结果操作
原始数组[6,1, 8 , 3 , 5 , 8 , 2 , 4 ]进行第一次遍历,比较6和1,位置不对交换
第一次交换结果[ 6 ,1, 8, 3 , 5 , 9 , 2 , 4 ]比较1和8,不交换
第二次交换结果[ 6 , 1 ,8,3, 5 , 9 , 2 , 4 ]比较8和3,交换
第三次交换结果[ 6 , 1 , 3 ,8,5, 9 , 2 , 4 ]比较8和5,交换
第四次交换结果[ 6 , 1 , 3 , 5 ,8,9, 2 , 4 ]比较8和9,不交换
第五次交换结果[ 6 , 1 , 3 , 5 , 8 ,9,2, 4 ]比较9和2,交换
第六次交换结果[ 6 , 1 , 3 , 5 , 8 , 2 ,9,4]比较9和4,交换
第七次交换结果[ 6 , 1 , 3 , 5 , 8 , 2 , 4 ,9]第一次有交换,遍历第二次
遍历第二次结果[ 1 , 3 , 5 , 6 , 2 , 4 ,8,9]第二次有交换,遍历第三次
遍历第三次结果[ 1 , 3 , 5 , 2 , 4 , 6,8,9]第三次有交换,遍历第四次
遍历第四次结果[ 1 , 3 , 2 , 4 , 5,6,8,9]第四次有交换,遍历第五次
遍历第五次结果[ 1 , 2 , 3 , 4,5,6,8,9]第五次有交换,遍历第六次
遍历第六次结果[1,2,3,4,5,6,8,9]第六次无交换,遍历结束

代码实现

    public static int[] sort(int[] sourceArray) throws Exception {//冒泡排序int length = sourceArray.length;//获取数组长度int[] arr = sourceArray;//拷贝数组//for循环用于进行书组遍历for (int i = 0; i < length ; i++) {int l = 0,r = 1;//定义左右指针int a = 0;//用于记录交换次数//while循环用于每次遍历下的数据交换while (l<length && r<length){if (arr[l] < arr[r] ) {//左小于右(正确顺序)针指i和j整体向右挪一个l++;r++;}else {//左大于右(不正确顺序)交换左右,然后针指i和j整体向右挪一个//交换左右int t = arr[l];arr[l] = arr[r];arr[r] = t;//然后针指i和j整体向右挪一个l++;r++;//记录交换次数a++;}}//判断此次遍历是否发生数据交换if (a == 0){break;}}//返回排序后的结果return arr;}

2.快速排序

原理

1.先从数列中取出一个数作为key值(标杆值);
2.将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;

挖坑填数字,每次比较都拿出一个标杆来和数据进行比较,先从右往左比,遇到比标杆小的就将其放在标杆的坑里(标杆数字所在的数组位置),换过去的数字所在位置成为新的坑,然后在从原来标杆的那个坑(刚刚放进数字的位置)从左往右比较,遇到比标杆数字大或等于的,就放在此时标杆位置所在的坑中,然后再从现在的这个刚放进去数字的坑从有往左比较,知道所有数字均符合左边比标杆小,右边比标杆大

3.对左右两个小数列重复第二步,直至各区间只有1个数。

示例

原始数组 :[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]
对原始数组进行第一个标杆的比较:

操作标杆数据结果下一步比较
拿出标杆数据6[ _, 1 , 8 , 3 , 5 , 9 , 2 , 4 ]<从右往左比,比较4和标杆数据
4小于标杆数据,4填坑6[4, 1 , 8 , 3 , 5 , 9 , 2 , _ ]>从左往右比,比较1和标杆数据
1小于标杆数据,不变6[4, 1 , 8 , 3 , 5 , 9 , 2 , _ ]>从左往右比,比较8和标杆数据
8大于标杆数据,8填坑6[4, 1 , _, 3 , 5 , 9 , 2 , 8 ]<从右往左比,比较2和标杆数据
2大于标杆数据,2填坑6[4, 1 , 2, 3 , 5 , 9 ,_, 8 ]>从左往右比,比较3和标杆数据
3小于标杆数据,不变6[4, 1 , 2,3 , 5 , 9 ,_, 8 ]>从左往右比,比较5和标杆数据
5小于标杆数据,不变6[4, 1 , 2, 3 , 5 , 9 ,_, 8 ]>从左往右比,比较9和标杆数据
9大于标杆数据,9填坑6[4, 1 , 2, 3 , 5 ,_ ,9, 8 ]左右比较交汇,该标杆放回坑内
标杆放回坑里[4, 1 , 2, 3 , 5 ,6 ,9, 8 ]该轮比较结束,对标杆6左右进行上述比较

对标杆两边重复上述操作:
(1)标杆6左边数据比较:得到:[ 1,2,3,4,5 ]

操作标杆数据结果下一步比较
拿出标杆数据4[ _ , 1 , 2, 3 , 5 ]<从右往左比,比较5和标杆数据
5大于标杆数据,不变4[ _ , 1 , 2, 3 , 5 ]<从右往左比,比较3和标杆数据
3小于标杆数据,3填坑4[3, 1 , 2, _ , 5 ]>从左往右比,比较1和标杆数据
1小于标杆数据,不变4[3, 1 , 2, _ , 5 ]>从左往右比,比较2和标杆数据
2小于标杆数据,不变4[3, 1 , 2, _ , 5 ]左右比较交汇,该标杆放回坑内
标杆放回坑里,对左右比较[3, 1 , 2, 4 , 5 ]该轮比较结束,对标杆4左右比较,右边只有一位不比较
标杆4左边比较3[2, 1 ,3 ]该轮比较结束,对标杆3左右比较,右边没有不比较
对标杆3左右比较2[ 1, 2 ]该轮比较结束,标杆左边只有一位,不再比较

(2)标杆6右边数据比较:得到:[ 8,9 ]

操作标杆数据结果下一步比较
拿出标杆数据9[ _, 8 ] <从右往左比,比较8和标杆数据
2小于标杆数据,8填坑9[ 8, _ ] 左右比较交汇,该标杆放回坑内
标杆放回坑里[ 8, 9 ]该轮比较结束,标杆左边只有一位,不再比较

最终的到数据:[ 1,2,3,4,5,6,8,9 ]

代码实现

public static void quickSort(int a[],int l,int r){if(l>=r)return;int i = l; int j = r; int key = a[l];//选择第一个数为标杆while(i<j){while(i<j && a[j]>=key)//从右向左找第一个小于标杆的值j--;if(i<j){a[i] = a[j];i++;}while(i<j && a[i]<key)//从左向右找第一个大于标杆的值i++;if(i<j){a[j] = a[i];j--;}}//i == ja[i] = key;quickSort(a, l, i-1);//递归调用quickSort(a, i+1, r);//递归调用}

3.插入排序

原理

1.将数组第一个数当成一个有序数组,然后从第二个数据开始看作无序数组
2.每次拿出无序数组中的第一个数据和有序数组的最后一位开始向前比较
3.将拿出的数据插入有序数组中的合适位置
4.重复上述步骤直至无序数组中所有的数据全部插入有序数组中。

示例

原始数组 :[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]

操作有序数组无序数组拿出来的数据
将数组分成有序数组和无序数组61、8、3、5、9、2、41
从后往前比较有序数组,将1插入有序数组1、68、3、5、9、2、48
从后往前比较有序数组,将8插入有序数组1、6 、83、5、9、2、43
从后往前比较有序数组,将3插入有序数组1、3、6 、85、9、2、45
从后往前比较有序数组,将5插入有序数组1、3、5、6 、89、2、49
从后往前比较有序数组,将9插入有序数组1、3、5、6 、8、92、42
从后往前比较有序数组,将2插入有序数组1、2、3、5、6 、8、944
从后往前比较有序数组,将4插入有序数组1、2、3、4、5、6 、8、9

代码实现

    public static void main(String[] args) {int[] nums={ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 };int start=1;for(start=1;start<nums.length;start++) {int insert=nums[start];//将数组第二个数据拿出放入insert,做为待插入的数据while(start>0) {if(nums[start-1]>insert) {//从后往前比较,遇到比该数字大的了就将大的数字往后挪一个位置nums[start]=nums[start-1];} else {//若遇到和拿出数字相同的数据,则将insert放入当前空缺位置nums[start]=insert;break;//结束当前循环}start--;//比较的数字往前挪一个}if(start==0) {nums[0]=start;}}for (int i = 0; i < nums.length; i++) {System.out.print(nums[i]+" ");}}

4.希尔排序

希尔排序也称递减增量排序,是对插入排序的改进,以牺牲稳定性的方法提高效率。

原理

1.根据数组长度确定增长量k2(k1 = length / 2)(例如:数组[ 1 , 5 , 3 , 8 , 9 , 3 ])
2.按照增量数列进行分组,一般分成k组(每组数据的两个数据相距k个位置,例如:k为3时,位置0和位置3一组,位置1和位置4一组,位置2和位置5一组)
3.比较每组的数据将其按照增量排序(比较:位置0和位置3数据,位置1和位置4数据,位置2和位置5数据,位置不对的交换)
4.确定增长量k2(k2 = k2 / 2)
5.按照增量数列进行分组,分为k2组(例如:k2 = 2 ,分组:位置0 位置2 位置4一组,位置1 位置3 位置5一组)
6.比较每组的数据将其按照增量排序
…(循环以上步骤直至k=1时为最后一趟)

示例

原始数组 :[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]

操作k值结果
计算k值,将原始数据分为k组46 , 1 , 8 , 3 , 5 , 9 , 2 , 4
四组分别排序(交换了第一组6,5 ,第三组8,2)45 , 1 , 2 , 3 , 6 , 9 , 8 , 4
重新计算k,将数据分为k组25, 1 , 2 , 3 , 6 , 9 , 8 , 4
两组分别排序22, 1 , 5 , 3 , 6 , 4 , 8 , 9
计算k,并分组12, 1 , 5 , 3 , 6 , 4 , 8 , 9
排序11, 2 , 3 , 4 , 5 , 6 , 8 , 9

代码实现

    public static void main(String[] args) {int[] nums={1,5,7,9,3,2,4,0,6,8,5};//控制增量序列,增量序列为1的时候为最后一趟for (int i = nums.length/2; i > 0; i/=2) {//根据增量序列,找到每组比较序列的最后一个数的位置for (int j = i; j <nums.length ; j++) {//根据该比较序列的最后一个数的位置,依次向前执行插入排序for (int k = j-i; k >= 0 ; k-=i) {if(nums[k]>nums[k+i]) {int tmp=nums[k];nums[k]=nums[k+i];nums[k+i]=tmp;}}}}System.out.println(Arrays.toString(nums));}

5.选择排序

原理

1.将数组中最小的数据拿出,放在数组第一个作为排序数组
2.在未排序数组中找出最小的,放在拍叙述组的尾部
3.循环执行,直到所有的数字排序完成

示例

原始数组 :[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]

操作排序数组未排序数组未排序数组中最小的
原始数组6 , 1 , 8 , 3 , 5 , 9 , 2 , 41
将1放在数组第一位最为排序数组 16 , 8 , 3 , 5 , 9 , 2 , 42
将1放在数组第一位最为排序数组1,26 , 8 , 3 , 5 , 9 , 43
将1放在数组第一位最为排序数组1,2,36 , 8 , 5 , 9 , 44
将1放在数组第一位最为排序数组1 ,2,3,46 , 8 , 5 , 95
将1放在数组第一位最为排序数组1 ,2,3,4,56 , 8 , 96
将1放在数组第一位最为排序数组1,2,3,4,5,68 , 98
将1放在数组第一位最为排序数组1,2,3,4,5,6,899
将1放在数组第一位最为排序数组1,2,3,4,5,6,8 ,9

代码实现

    public static void main(String[] args) {int[] nums={1,5,7,9,3,2,4,0,6,8,5};int start=1;for(start=1;start<nums.length;start++) {int insert=nums[start];while(start>0) {if(nums[start-1]>insert) {nums[start]=nums[start-1];} else {nums[start]=insert;break;}start--;}if(start==0) {nums[0]=start;}}for (int i = 0; i < nums.length; i++) {System.out.print(nums[i]+" ");}}

6.堆排序

堆排序是一种选择排序
堆是一颗完全二叉树:
当所有的结点的值都大于或等于其左右的子结点的值称为大顶堆
当所有的结点的值都小于或等于其左右的子结点的值称为小顶堆

原理

1.先将数组排序成一个大根堆
2.将根节点和最后一个叶子借点交换
3.将非最后一个叶子节点的其他数据排序成大根堆(此时最后一个叶子节点为上一轮排序中的根节点,最大的数据,位置已经确定了)
4.交换该大根堆中的根节点和最后一个叶子结点
…(循环直到所有数据均排列完成)

示例

操作数组
原始数组6 , 1 , 8 , 3 , 5 , 9 , 2 , 4
第一轮大根堆交换节点后结果3,5,8,4,1,6,2,9
第二轮大根堆交换节点后结果2,5,6,4,1,3,89
第三轮大根堆交换节点后结果2,5,3,4,1,689
第四轮大根堆交换节点后结果1,4,3,2,5689
第五轮大根堆交换节点后结果1,2,3,45689
第六轮大根堆交换节点后结果1,2,345689
第七轮大根堆交换节点后结果1,2345689
第八轮大根堆交换节点后结果12345689

具体过程:
在这里插入图片描述

代码实现

import java.util.Arrays;public class HeapSort {public static void main(String[] args) {int[] arr = {3, 5, 2, 7,4,5,8,2,1,9,0,5,4};heapSort(arr);System.out.println(Arrays.toString(arr));}//堆排序public static void heapSort(int[] arr) {//将无序序列构建成一个堆for (int i = arr.length / 2 - 1; i >= 0; i--) {adjustHeap(arr, i, arr.length);}//将堆顶元素和末尾元素交换,将最大元素放置数组末端//重新调整至堆结构,然后继续将堆顶元素和当前末尾元素交换,以此往复for (int i = arr.length - 1; i > 0; i--) {int temp = arr[i];arr[i] = arr[0];arr[0] = temp;adjustHeap(arr, 0, i);}}// 将二叉树调整为堆public static void adjustHeap(int[] arr, int i, int length) {int temp = arr[i];//k=2i+1是i的左子结点for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {if (k + 1 < length && arr[k] < arr[k + 1])//左子结点的值<右子结点的值k++;//指向右节点if (arr[k] > temp) {//如果子结点的值>根节点的值arr[i] = arr[k];//将较大的值赋给当前结点i = k;//i指向k,继续循环比较} elsebreak;}//for循环后,已经将以i为根结点的树的最大值,放在了顶部arr[i] = temp;//将temp值放到调整后的位置}
}

7.归并排序

原理

1.将数组分成不同的组,每次平均分成两个数组,直到无法分成两份
2.将两个长度为1的数组合并成一个长度为2的有序数组
3.将两个长度为2的数组合并成一个长度为4的有序数组
…(重复多遍)
4.直至和并完成

示例

操作数组结果
原始数组[ 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 ]
[ 6 , 1 , 8 , 3 ] 、 [ 5 , 9 , 2 , 4 ]
[ 6 , 1 ] 、 [ 8 , 3 ] 、 [ 5 , 9 ] 、 [2 , 4 ]
[ 6 ]、 [1 ] 、 [ 8 ]、 [ 3 ] 、 [ 5 ] 、 [9 ] 、 [2 ]、 [ 4 ]
[1 , 6 ] 、[ 3 , 8 ] 、 [ 5 , 9 ] 、[ 2 , 4 ]
[1 , 3 , 6 ,8 ] 、 [ 2, 4 ,5 ,9 ]
[ 1,2,3,4,5,6,8,9 ]

代码实现

public class Test {public static void main(String[] args) {int[] arr = { 6 , 1 , 8 , 3 , 5 , 9 , 2 , 4 };int[] temp = new int[arr.length];//归并排序需要额外的数组空间mergeSort(arr, 0, arr.length - 1, temp);//将数组分成最小单元System.out.println(Arrays.toString(arr));}//分public static void mergeSort(int[] arr, int left, int right, int[] temp) {if (left < right) {int mid = (left + right) / 2;//中间索引mergeSort(arr, left, mid, temp);//向左递归分解数组mergeSort(arr, mid + 1, right, temp);//向右递归分解数组merge(arr, left, mid, right, temp);//分解完成后将数组进行合并}}//治public static void merge(int[] arr, int left, int mid, int right, int[] temp) {int i = left;//i为指向左边序列第一个元素的索引int j = mid + 1;//j为指向右边序列第一个元素的索引int t = 0;//指向临时temp数组的当前索引//先把左右两边有序数据按规则存入temp数组中,直到有一边的数据全部填充temp中while (i <= mid && j <= right) {if (arr[i] <= arr[j]) {temp[t] = arr[i];t++;i++;} else {temp[t] = arr[j];t++;j++;}}//将有剩余数据的一边全部存入temp中while (i <= mid) {//左边序列有剩余元素temp[t] = arr[i];t++;i++;}while (j <= right) {//右边序列有剩余元素temp[t] = arr[j];t++;j++;}t = 0;int tempLeft = left;while (tempLeft <= right) {arr[tempLeft] = temp[t];t++;tempLeft++;}}
}

感谢您对大饼的支持
今天的你也很辛苦,晚安,明天见

在这里插入图片描述

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

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

相关文章

21.6 CSS 弹性布局

1. 弹性盒子 CSS弹性盒子(Flexbox)是一种布局模型, 用于创建灵活的, 自适应的网页布局. 它的目的是在不同屏幕尺寸和设备上实现一致的布局效果.引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列, 对齐和分配空白空间.弹性容器通过设置display…

左值、右值、左值引用和右值引用

左值、右值和左值引用&#xff0c;在C11之前&#xff0c;我们都很熟悉也都很好理解。左值(LValue)就是有名字能够寻址的对象的值类型&#xff0c;右值就是在内存上没有名字的数值的值类型&#xff0c;左值引用就是指向左值的引用。 C11引入了右值引用&#xff0c;从而可以去读…

STM32 CubeMX ADC采集(HAL库)

STM32 CubeMX ADC采集&#xff08;HAL库&#xff09; STM32 CubeMX STM32 CubeMX ADC采集&#xff08;HAL库&#xff09;ADC介绍ADC主要特征最小识别电压值&#xff1a;2.4/4096≈0.6mv&#xff08;不考虑误差&#xff09;一、STM32 CubeMX设置二、代码部分三&#xff0c;单通道…

泛微OA e-office平台uploadify.php任意文件上传漏洞

泛微OA e-office平台uploadify.php任意文件上传漏洞复现 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的…

玩转Linux—如何在Linux环境中部署MySQL、Redis和nginx

1、Linux常用命令 Linux学习之路&#xff1a; VMware虚拟机安装Linux系统(详解版) 查看当前文件目录&#xff1a;ls查看目录中文件详细信息&#xff1a;ll输出当前所处的目文件目录&#xff1a;pwdLinux查看当前IP地址&#xff1a;ifconfigWindows查看当前IP地址&#xff1…

基于SpringBoot的民宿在线预定平台

目录 前言 一、技术栈 二、系统功能介绍 用户信息管理 民宿信息管理 民宿资讯管理 民宿分类管理 用户注册 民宿信息 我的订单 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实…

通过IP地址管理提升企业网络安全防御

在今天的数字时代&#xff0c;企业面临着越来越多的网络安全威胁。这些威胁可能来自各种来源&#xff0c;包括恶意软件、网络攻击和数据泄露。为了提高网络安全防御&#xff0c;企业需要采取一系列措施&#xff0c;其中IP地址管理是一个重要的方面 1. IP地址的基础知识 首先&a…

【观察】天翼云政务大模型“慧泽”:推动政务服务再升级,加速智慧城市再进化...

进入2023年以来&#xff0c;AIGC的爆发式增长推动了全球步入一个全新时代——大模型时代&#xff0c;它不仅引发了AI产业的整体升级换代&#xff0c;同时大模型与行业和应用场景的深度融合&#xff0c;更加速了AI的“走深向实”。 其中&#xff0c;政务业务不仅是连接政府、企业…

mstp vrrp bfd 实验

LSW1配置 <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sys lsw1 [lsw1]vlan batch 10 20 30 [lsw1]int g0/0/1 [lsw1-GigabitEthernet0/0/1]port link-type access [lsw1-GigabitEthernet0/0/1]port default vlan 10 [lsw1-GigabitEthernet0…

Docker---cgroups资源限制

目录 一、cpu资源控制 1、 设置cpu使用率上限 2、设置cpu资源占用比&#xff08;设置多个容器时才有效&#xff09; 3、设置容器绑定指定的CPU 三、内存资源控制 四、磁盘IO配额控制 1、限制Block IO 2、限制bps和iops进行限制 一、cpu资源控制 cgroups是一个非常强大的…

用合成数据训练车辆姿态估计神经网络

我们的客户希望开发一款应用程序&#xff0c;引导用户通过 AR 指南和自动照片拍摄来拍摄更高质量的汽车照片。 本文重点介绍构建汽车姿态估计组件的技术。 在应用程序中&#xff0c;用户被引导站在与汽车一定的角度和距离&#xff0c;以标准化的方式捕捉最好的照片。 当用户处于…

LLMs Python解释器程序辅助语言模型(PAL)Program-aided language models (PAL)

正如您在本课程早期看到的&#xff0c;LLM执行算术和其他数学运算的能力是有限的。虽然您可以尝试使用链式思维提示来克服这一问题&#xff0c;但它只能帮助您走得更远。即使模型正确地通过了问题的推理&#xff0c;对于较大的数字或复杂的运算&#xff0c;它仍可能在个别数学操…