算法 经典的八大排序算法详解和代码实现

  • 排序算法的介绍
    • 排序的分类
  • 算法的时间复杂度
    • 时间频度
    • 示例
    • 图表理解时间复杂度的特点
  • 时间复杂度
    • 常见的时间复杂度
  • 空间复杂度
  • 排序算法的时间复杂度
  • 冒泡排序
    • 基本思想
    • 图解
    • 代码示例
    • 结果展示
    • 代码优化
    • 结果展示
  • 选择排序
    • 基本思想
    • 图解
    • 代码实现
    • 结果展示
  • 插入排序
    • 基本思想
    • 图解
    • 代码实现
    • 结果展示
  • 希尔排序
    • 基本思想
    • 图解
    • 代码实现
    • 结果展示
  • 快速排序
    • 基本思想
    • 图解
    • 代码实现
    • 结果展示
  • 归并排序
    • 基本思想
    • 图解
    • 代码实现
    • 结果展示
  • 基数排序
    • 基本思想
    • 图解
    • 代码实现

排序算法的介绍

排序也称排序算法,排序时将一组数据,依指定的顺序进行排列的过程

排序的分类

内部排序,指将需要处理的所有数据都加载到内部内存中进行排序

外部排序,数据量很大,无法全部加载到内存中,需要借助外部存储进行排序,内存和外存结合

算法的时间复杂度

时间频度

时间频度:一个算法花费的时间与算法中语句的执行次数成正比,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。即为T(n).

示例

比如计算1-100所有数字之和,我们设计两种算法:

1.使用for循环计算

int total=0;
int end=100;
for(int i=1;i <=end;i++){total+=i;
}

使用for循环的时间频度:T(n)=n+1

2.直接计算

total=(1+end)*end/2;

直接计算的时间频度:T(n)=1

图表理解时间复杂度的特点

1.常数项可以忽略

2.低次项可以忽略

3.系数可以忽略

随着n增大的结果如下图:

结论:

2n+20和2n随着n变大,执行曲线无限接近,20可以忽略

3n+10和3n随着n变大,执行曲线无限接近,10可以忽略

结论:

算式随着n变大,同次方项执行曲线无限接近,低次项可以忽略

结论:

随着n变大,同次方项曲线近似重合,系数可以忽略

时间复杂度

1)一般情况下,算法中的基本操作语句的重复执行次数是问题规模n的某个函数,用T(n)表示,若有个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。

2)T(n)不同,但时间复杂度可能相同。如:T(n)=n2+7n+6与T(n)=3n2+2n+2它们的T(n)不同,但是时间复杂度相同都为O(n^2)

3)计算时间复杂度的方法:

  • 用常数1代替运行时间中的所有加法常熟
  • 修改后的运行次数函数中,只保留最高阶项
  • 去除最高阶项的系数

常见的时间复杂度

空间复杂度

空间复杂度该算法所耗费的存储空间

在做算法分析时,主要讨论的是时间复杂度。

排序算法的时间复杂度

冒泡排序

基本思想

基本思想:通过对待排序序列从前向后,依次比较元素相邻元素的值,若发现逆序则变换,使值较大的元素逐渐从前移向后部,就像水底的气泡一样逐渐向上冒;

图解

小结:

  • 一共进行数组长度的减1次循环
  • 每一趟排序的次数在逐渐减少
  • 如果相邻的逆序就交换

代码示例

public class BubbleSort {public static void main(String[] args) {int arr[] = {11, 3, 17, 5, 9, 20,-1};System.out.println("排序前:");System.out.println(Arrays.toString(arr));System.out.println("过程展示:");for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}System.out.println(Arrays.toString(arr));}System.out.println("排序后:");System.out.println(Arrays.toString(arr));}
}

结果展示

代码优化

public class BubbleSort {public static void main(String[] args) {int[] arr = {11, 3, 17, 5, 9, 20,21};System.out.println("排序前:");System.out.println(Arrays.toString(arr));System.out.println("过程展示:");boolean flag=false;for (int i = 0; i < arr.length - 1; i++) {for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {flag=true;int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}if (!flag) {//在一趟排序中,一次交换都没有发生过break;}else{flag=false;}System.out.println(Arrays.toString(arr));}System.out.println("排序后:");System.out.println(Arrays.toString(arr));}
}

结果展示

选择排序

基本思想

每次找到最大值(最小值),从最后一位(最前一位)进行交换,依次向前(向后)交换,得到一个从小到大排列的有序序列

图解

结论:

  • 选择排序一共有数组的长度减1轮排序
  • 每一轮排序又是一个循环
  • 假定第一个数是最小数,然后和后面依次进行比较,从而确定最小数,并得到下标,然后进行交换

代码实现

public class SelectSort {public static void main(String[] args) {int[] arr={1,4,2,76,34,12};System.out.println("原数据:");System.out.println(Arrays.toString(arr));selectSort(arr);System.out.println("排序后:");System.out.println(Arrays.toString(arr));}//选择排序public static void selectSort(int arr[]) {for (int i = 0; i < arr.length - 1; i++) {int min = arr[i];int minIndex = i;for (int j = i+1; j < arr.length; j++) {if (min > arr[j]) {min = arr[j];minIndex = j;}}if (minIndex!=i) {arr[minIndex]=arr[i];arr[i]=min;}System.out.println("第"+(i+1)+"轮后~~");System.out.println(Arrays.toString(arr));}}
}

结果展示

插入排序

基本思想

把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表

图解

代码实现

public class InsertSort {public static void main(String[] args) {int[] arr = {2, 4, 32, 12, 45, 2, 1, 4};System.out.println("排序前:");System.out.println(Arrays.toString(arr));System.out.println("排序过程:");insetSort(arr);System.out.println("排序后:");System.out.println(Arrays.toString(arr));}public static void insetSort(int[] arr) {for (int i = 1; i < arr.length; i++) {int value = arr[i];//假设是插入的数int index = i-1;//插入的数的前面一个数while (index >= 0 && value < arr[index]) {arr[index + 1] = arr[index];index--;}arr[index + 1] = value;System.out.println(Arrays.toString(arr));}}
}

结果展示

希尔排序

基本思想

希尔也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键字越来越多,当增量减至1时,整个文件恰被分成一组,算法并终止

图解

在这里插入图片描述

代码实现

交换法:

public class ShellSort {public static void main(String[] args) {int[] arr={1,4,2,3,8,5,9,6,7};System.out.println("排序前:");System.out.println(Arrays.toString(arr));shellSort(arr);System.out.println("排序后:");System.out.println(Arrays.toString(arr));}private static void shellSort(int[] arr){int temp = 0;int count = 0;//一共gap组for(int gap=arr.length/2;gap>0;gap/=2){//遍历各组中的所有元素for(int i=gap;i < arr.length;i++){//如果当前元素大于加上步长后的那个元素,说明交换for(int j = i -gap;j>=0;j-=gap){if(arr[j]>arr[j+gap]){temp=arr[j];arr[j]=arr[j+gap];arr[j+gap]=temp;}}}System.out.println("希尔排序第"+(++count)+"轮");System.out.println(Arrays.toString(arr));}}
}

移位法:

  public static void shellSort2(int[] arr) {for (int gap = arr.length / 2; gap > 0; gap /= 2) {for (int i = gap; i < arr.length; i++) {int j = i;int temp = arr[j];if (arr[j] < arr[j - gap]) {while (j - gap >= 0 && temp < arr[j - gap]) {arr[j] = arr[j - gap];j -= gap;}arr[j] = temp;}}System.out.println(Arrays.toString(arr));}}
}

结果展示

1.交换法

2.移动法

快速排序

基本思想

快速排序是对冒泡排序的一种改进;通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有的数据都要小,然后再按此方法对者两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

图解

代码实现

public class QuickSort {public static void main(String[] args) {int[] arr={1,5,3,-1,544,3,45,6,23,22,15};quickSort(arr,0,arr.length-1);System.out.println("arr"+ Arrays.toString(arr));}public static void quickSort(int[] arr,int left,int right){int temp=0;int l=left;//左下标int r=right;//右下标int pivot=arr[(left+right)/2];//中轴值while (l < r) {while (arr[l] < pivot) {l+=1;}while (arr[r] > pivot) {r-=1;}if (l >= r) {break;}temp=arr[l];arr[l]=arr[r];arr[r]=temp;if (arr[l]==pivot) {r-=1;}if (arr[r]==pivot) {l+=1;}}if(l==r){l+=1;r-=1;}//向左递归if (left < r) {quickSort(arr,left,r);}//向右递归if (right > l) {quickSort(arr,l,right);}}
}

结果展示

归并排序

基本思想

本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。分阶段可以理解位就是递归拆分子序列的过程

图解

代码实现

public class MergeSort {public static void main(String[] args) {int[] arr={8,4,5,7,1,3,6,2};System.out.println("排序前:"+Arrays.toString(arr));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);}}/**** @param arr 排序的原始数组* @param left 左边有序序列的初始索引* @param mid 中间索引* @param right 右边索引* @param temp 做中转的数组*/public static void merge(int[] arr,int left,int mid,int right ,int[] temp){int i= left;int j=mid+1;int t=0;//指向temp数组的当前索引while(i<=mid && j<=right){if (arr[i]<=arr[j]) {temp[t]=arr[i];t+=1;i+=1;}else{temp[t]=arr[j];t+=1;j+=1;}}while (i <= mid) {temp[t]=arr[i];t+=1;i+=1;}while (j <= right) {temp[t]=arr[j];t+=1;j+=1;}t=0;int tempLeft=left;while (tempLeft <= right) {arr[tempLeft]=temp[t];t +=1;tempLeft+=1;}}

结果展示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e47XKM5S-1640004020334)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211220192324138.png)]

基数排序

基本思想

基数排序属于‘’分配式排序‘’,又称‘’桶子法‘’或bin sort,它是通过键值的各个位的值,将要排序的元素分配至某些‘’桶‘’中,达到排序的作用

是桶排序的扩展,属于稳定性的排序

将所有带比较数值统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行依次排序。这样从最低为排序一直到最高位排序完成以后,数列就变成一个有序序列。

图解

代码实现

public class RadixSort {public static void main(String[] args) {int arr[]={53,3,542,748,14,214};radixSort(arr);}public static void radixSort(int[] arr){int max=arr[0];for (int i = 0; i < arr.length; i++) {if (arr[i] > max) {max=arr[i];}}int maxLength=(max+"").length();int[][] bucket=new int[10][arr.length];int[] bucketElementCounts=new int[10];for(int j=0,n=1;j<maxLength;j++,n*=10) {for (int i = 0; i < arr.length; i++) {int digitOfElement = arr[i]/n % 10;bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];bucketElementCounts[digitOfElement]++;}int index = 0;for (int k = 0; k < bucket.length; k++) {if (bucketElementCounts[k] != 0) {for (int l = 0; l < bucketElementCounts[k]; l++) {arr[index] = bucket[k][l];}}bucketElementCounts[k]=0;}System.out.println(Arrays.toString(arr));}}
}

算法 经典的八大排序算法详解和代码实现相关推荐

  1. 调包侠福音!机器学习经典算法开源教程(附参数详解及代码实现)

    Datawhale 作者:赵楠.杨开漠.谢文昕.张雨 寄语:本文针对5大机器学习经典算法,梳理了其模型.策略和求解等方面的内容,同时给出了其对应sklearn的参数详解和代码实现,帮助学习者入门和巩固 ...

  2. 数据结构与算法--经典10大排序算法(动图演示)【建议收藏】

    十大经典排序算法总结(动图演示) 算法分类 十大常见排序算法可分为两大类: 比较排序算法:通过比较来决定元素的位置,由于时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序 非比较类型排 ...

  3. 【数据结构】八大排序(超详解+附动图+源码)

    目录 前言 常见排序算法的实现 1.插入排序 2.希尔排序 3.选择排序 4.堆排序 5.冒泡排序 6.快速排序 6.1 hoare版本 6.2挖坑法 6.3前后指针法 6.4快速排序优化 6.5快速 ...

  4. 八大排序算法java_java实现八大排序算法

    Arrays.sort() 采用了2种排序算法 -- 基本类型数据使用快速排序法,对象数组使用归并排序. java的Collections.sort算法调用的是归并排序,它是稳定排序 方法一:直接插入 ...

  5. 希尔排序(详解与代码)

    希尔排序算是对简单插入排序的一种改进,属于一种增量式的排序算法. 还不明白希尔排序概念的,先看这个希尔排序介绍 直接放代码 package com.lingaolu;/*** @author 林高禄* ...

  6. 数据结构与算法之选择排序图文详解及代码 (C++实现)

    实现: #include<iostream> using namespace std; #define MAXSIZE 20//顺序表的最大长度 typedef int KeyType;/ ...

  7. 数据结构之希尔排序图文详解及代码(C++实现)

    问题: 对待排序的数组r[1..n]中的元素进行直接插入排序,得到一个有序的(从小到大)的数组r[1..n]. 算法思想: 1.第一趟取增量d1(d1<n)把全部记录分为d1个组,所有间隔为d1 ...

  8. 数据结构之堆栈排序图文详解及代码(C++实现)

    代码: #include<iostream> using namespace std; #define MAXSIZE 20//顺序表的最大长度 typedef int KeyType;/ ...

  9. Python实现八大排序算法(转载)+ 桶排序(原创)

    插入排序 核心思想 代码实现 希尔排序 核心思想 代码实现 冒泡排序 核心思想 代码实现 快速排序 核心思想 代码实现 直接选择排序 核心思想 代码实现 堆排序 核心思想 代码实现 归并排序 核心思想 ...

最新文章

  1. mysql游标结果为空
  2. 【网页前端设计Front end】HTML语言基础.下(看不懂你来打我)
  3. java 存入对象io_Java面向对象 IO (一)
  4. sphinx-release 2.1.4
  5. Feature Flag 功能发布控制
  6. 036 关于网站的UV分析
  7. Sigmoid 函数
  8. 道路照明智能监控用5G智慧灯杆网关
  9. 二、自然语言处理发展历程
  10. 什么是单臂路由?单臂路由的优缺点?如何配置单臂路由?
  11. opencv出现0x75BA812F 处(位于 Project1.exe 中)有未经处理的异常: Microsoft C++ 异常的一种可行解决方案
  12. java项目-第150期ssm网络视频播放器-java毕业设计_计算机毕业设计
  13. Python————办公自动化
  14. 配置常用yum源(国内yum源)
  15. ExecutionException 异常类解析
  16. 计算机的信息表示(进制的转换)
  17. Win7下的Linux通过Nat的VMnet8下的NAT方式进行上网
  18. UI设计师如何应对面试 哪些细节问题不可忽视
  19. Java航班预订统计leetcode_1109
  20. python基于PHP旅游网站的设计与开发

热门文章

  1. 建表添加描述 mysql_MySQL建表语句+添加注释
  2. sqlite mysql_两款主流数据库对比,SQLite和MySQL哪款是你的菜?
  3. VMware Workstation 无法连接到虚拟机
  4. 计算机等级一级最好还是,计算机等级考试一级哪个好考
  5. 安卓微信自动抢红包插件实现和优化
  6. 成都正规python培训班
  7. win11共享打印机修复工具V1.0 | 完美解决“Windows无法连接到打印机、找不到打印机”以及“操作无法完成错误0x00000bc4找不到打印机”问题!!!
  8. matlab 小波包分解信号获取时频图
  9. eclipse对应版本安装的STS插件下载地址,使用springboot
  10. 【java】——配置文件报错:不允许有匹配 [xX][mM][lL] 的处理指令目标。