冒泡排序

原理

假设有10个数,第一轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动;接着第二个数和第三个数比较,如果第二个数大,第二个数和第三个数交换位置,否则不动……第九个数和第十个数比较,如果第九个数大,第九个数和第十个数交换位置,否则不动。第一轮循环结束,最大的数挪到了第十个数的位置,比较进行了9次。 (注意:第一轮循环结束后,第十个数的位置已经固定,它是这些数里的最大值,不再需要比较)
第二轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动……第八个数和第九个数比较,如果第八个数大,第八个数和第九个数交换位置,否则不动。第二轮循环结束,第二大的数挪到了第九个数的位置,比较进行了8次。
……
第九轮循环,第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动。第九轮循环结束,倒数第二大的数挪到了第二个数的位置,比较进行了1次。

即:每次比较两个相邻的元素,将较大的元素交换至右端。

图解



Java实现

import java.util.Arrays;public class BubbleSort {public static void main(String[] args) {int[] arr = {2,10,65,88,5,8,1};BubbleSort b = new BubbleSort();b.bubblesort(arr);
//      BubbleSort.bubblesort(arr);     //  bubblesort方法 加 staticSystem.out.println(Arrays.toString(arr));}public void bubblesort(int[] arr){int temp;if(arr.length<=1){return;}//控制冒泡次数for(int i=0;i<arr.length-1;i++){//控制冒泡的比较次数//(可结合图理解 --冒泡次数每增加1,对应比较的次数相应减少1,体现在i上)for(int j=0;j<arr.length-1-i;j++){if(arr[j+1]<arr[j]){//相邻元素两两对比,如果是逆序的,则进行元素交换temp=arr[j+1];arr[j+1]=arr[j];arr[j]=temp;}}}}
}

注意:为什么 j < arr.length-1-i

第一轮循环: 每次比较两个相邻的元素,将较大的元素交换至右端。
第二轮循环:比较和上一轮几乎一样,只不过比较次数比第一次少1次 (因为最右端已经是最大数,无需再比较)
第三轮循环:比较和上一轮几乎一样,只不过比较次数比第二次少1次
……
综上,每增加一轮循环,我们的比较次数减1。
因此,我们要复用内循环,而循环的轮数由 i < arr.length - 1 决定,那么,我们要使它每轮循环后对于比较次数进行递减,则,可以再嵌套循环,将条件改为 j < arr.length-1-i ;i 从零递增,那么第一次,内循环执行了 arr.length - 1-0次;第二次,内循环执行了 arr.length - 1-1……第九次执行了arr.length-1-8次(arr.length=10)

运行结果

冒泡之前的数组:[2, 10, 65, 88, 5, 8, 1]
开始冒泡:[2, 10, 65, 88, 5, 8, 1]
开始冒泡:[2, 10, 65, 88, 5, 8, 1]
开始冒泡:[2, 10, 65, 88, 5, 8, 1]
开始冒泡:[2, 10, 65, 5, 88, 8, 1]
开始冒泡:[2, 10, 65, 5, 8, 88, 1]
开始冒泡:[2, 10, 65, 5, 8, 1, 88]
开始冒泡:[2, 10, 65, 5, 8, 1, 88]
开始冒泡:[2, 10, 65, 5, 8, 1, 88]
开始冒泡:[2, 10, 5, 65, 8, 1, 88]
开始冒泡:[2, 10, 5, 8, 65, 1, 88]
开始冒泡:[2, 10, 5, 8, 1, 65, 88]
开始冒泡:[2, 10, 5, 8, 1, 65, 88]
开始冒泡:[2, 5, 10, 8, 1, 65, 88]
开始冒泡:[2, 5, 8, 10, 1, 65, 88]
开始冒泡:[2, 5, 8, 1, 10, 65, 88]
开始冒泡:[2, 5, 8, 1, 10, 65, 88]
开始冒泡:[2, 5, 8, 1, 10, 65, 88]
开始冒泡:[2, 5, 1, 8, 10, 65, 88]
开始冒泡:[2, 5, 1, 8, 10, 65, 88]
开始冒泡:[2, 1, 5, 8, 10, 65, 88]
开始冒泡:[1, 2, 5, 8, 10, 65, 88]
冒泡之后的数组:[1, 2, 5, 8, 10, 65, 88]

快速排序

原理

快速排序的基本思想: 取一个标准位置的数字 ,与其他位置的数字进行对比 。如果比标准数大 ,则放到标准数的右边,如果比标准数小 , 则放到标准数的左边 。

版本一:

假设我们现在对 " 6 1 2 7 9 3 4 5 10 8 " 这个10个数进行排序。
首先在这个序列中随便找一个数作为基准数(就是一个用来参照的数)。为了方便,就让第一个数6作为基准数。接下来,需要将这个数组中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列:
3 1 2 5 4 6 9 7 10 8

在初始状态下,数字6在数组的第0位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。

分别从初始数组 “ 6 1 2 7 9 3 4 5 10 8 ” 两端开始“探测”。先从右往左找一个小于6的数,再从左往右找一个大于6的数,然后交换找出来的这两个数。这里可以用两个变量 i 和 j ,分别指向数组最左边数的下标的和数组最右边数的下标。

数组 : 6 1 2 7 9 3 4 5 10 8
下标 : 0 1 2 3 4 5 6 7 8 9

刚开始的时候让 i 指向数组的最左边(即i=1),指向数字6 。让 j 指向数组的最右边(即j=10),指向数字8。

首先 j 开始移动。因为此处设置的基准数是最左边的数,所以需要让 j 先移动。j 从右向左移动(即 j–),直到找到一个小于6的数停下来。接下来 i 再从左向右挪动(即 i++),直到找到一个数大于6的数停下来。最后 j 停在了数字5面前, i 停在了数字7面前。

按照规则,交换 比基准数小的数(j=5)和比基准数大的数(i=7)。交换之后的数组如下:
数组 : 6 1 2 5 9 3 4 7 10 8

第一次交换结束。
j 继续从右向左挪动(每次必须是 j 先开始移动)。j 找到了4(比基准数6小)之后停了下来。
i 继续从左向右挪动 ,i 找到9(比基准数6大)之后停了下来。
此时再次进行交换,交换之后的数组如下:
数组 : 6 1 2 5 4 3 9 7 10 8
下标 : 0 1 2 3 4 5 6 7 8 9

第二次交换结束,j 继续从右向左挪动,j 找到了3(比基准数6小)之后又停了下来。注意:此时 j 在数字3的位置——6。 i 继续向右移动,**注意!!!**因为需要从左往右寻找比基准数6大的数,所以一直到数字3(位置6),也没找到符合条件的数字。此时 i 和 j 的值相等了,i 和 j 都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的数组如下:
数组 : 3 1 2 5 4 6 9 7 10 8

此时,在数组中,元素6左边的数都比它小,元素6右边的数都比它大。
将原数组以6为分界点拆分成了两个数组,左边的数组是 “ 3 1 2 5 4 ” ,右边的数组是 “ 9 7 10 8 ” 。接下来还需要分别处理这两个数组。

左边的数组是:
数组: 3 1 2 5 4
下标: 0 1 2 3 4
将这个数组以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。
j 从右往左开始查找比3小的数,找到数字2,下标为2。
i 从左往右开始查找比3大的数,一直到数字2,没找到满足条件的数,此时i 和 j 的值相同,都指向3,因此,结束查找,交换基准数和3的位置

调整完毕之后的数组:
2 1 3 5 4

此时3左边的数都比它小,右边的数都比它大。
接下来处理3左边的数组 “ 2 1 ” 和右边的数组 “ 5 4 ”。
对数组 “ 2 1 ” 以2为基准数进行调整,处理完毕之后的数组为 “ 1 2 ”。
数组 “ 5 4 ” 的处理同理,最后得到的数组如下:
1 2 3 4 5

对于数组 “ 9 7 10 8 ” 的处理同理。最终将会得到结果数组:
1 2 3 4 5 6 7 8 9 10

版本二:
https://blog.csdn.net/qq_36186690/article/details/82470451

图解

Java实现

import java.util.Arrays;public class QuickSort {public static void main(String[] args) {// TODO Auto-generated method stubint[] arr = {3,9,6,1,2,5,4,7,10,8};QuickSort.quicksort(arr, 0, arr.length - 1);System.out.println("快速排序的结果:"+Arrays.toString(arr));}public static void quicksort(int[] a, int left, int right) {//a 是需要排序的数组、 left 是数组中第一个数的下标、 right 是最后一个数的下标int i, j, t, temp;//当数组有数据时,才开始进行排序if(left > right){return;}System.out.println("初始数组:"+Arrays.toString(a));temp = a[left]; //temp中存的就是基准数System.out.println("基准数temp:"+temp);i = left;j = right;System.out.println("初始a[j]="+a[j]);System.out.println("初始a[i]="+a[i]);System.out.println("---------------开始进行快速排序---------------");//当i=j时候,则进行将基准数放置“中间位置”,否则,运行下列逻辑while(i != j&& i < j) { /** 先从右往左,找比基准数小的数* 注意:* 快排的思想是 每一次取一个小于基准数的数 和 一个大于基准数的数,然后交换他们的位置* 为了保证一次只取一个数* 设置限制条件:a[j] >= temp,* 找到比基准数大的则 j-- 继续往下找,直到找到比基准数temp小的数,则跳出循环,进行数据的交换* 否则,若是a[j] <= temp,* 则取出所有比temp小的数(直到遇到一个“大数”),无法实现取一个“小数据”就交换一个* * 可以参照之后的运行结果进行理解*/while(a[j] >= temp && i < j){j--; }// i从左往右移,直到遇到比基准数大的数while(a[i] <= temp && i < j){i++;}if( i < j)//交换两个数在数组中的位置{System.out.println("---------------开始交换---------------");t = a[i];a[i] = a[j];a[j] = t;System.out.println("交换之后的数组:"+Arrays.toString(a));System.out.println("---------------交换结束---------------");}}//最终将基准数归位,即将基准数放到中间位置,基准数左边的数都小于它,右边的数都大于它a[left] = a[i];a[i] = temp;System.out.println("排序之后的数组:"+Arrays.toString(a));System.out.println("=============================================");System.out.println();//此时基准数(下标为i)在中间位置,左边的数都比基准数小,右边的数都比基准数大quicksort(a,left, i-1);//继续处理左边的,这里是一个递归的过程quicksort(a,i+1, right);//继续处理右边的 ,这里是一个递归的过程}}

运行结果


初始数组:[3, 9, 6, 1, 2, 5, 4, 7, 10, 8]
基准数temp:3
初始a[j]=8
初始a[i]=3
---------------开始进行快速排序---------------
---------------开始交换---------------
交换之后的数组:[3, 2, 6, 1, 9, 5, 4, 7, 10, 8]
---------------交换结束---------------
---------------开始交换---------------
交换之后的数组:[3, 2, 1, 6, 9, 5, 4, 7, 10, 8]
---------------交换结束---------------
排序之后的数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
基准数temp:1
初始a[j]=2
初始a[i]=1
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
基准数temp:2
初始a[j]=2
初始a[i]=2
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 6, 9, 5, 4, 7, 10, 8]
基准数temp:6
初始a[j]=8
初始a[i]=6
---------------开始进行快速排序---------------
---------------开始交换---------------
交换之后的数组:[1, 2, 3, 6, 4, 5, 9, 7, 10, 8]
---------------交换结束---------------
排序之后的数组:[1, 2, 3, 5, 4, 6, 9, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 5, 4, 6, 9, 7, 10, 8]
基准数temp:5
初始a[j]=4
初始a[i]=5
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 9, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 4, 5, 6, 9, 7, 10, 8]
基准数temp:4
初始a[j]=4
初始a[i]=4
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 9, 7, 10, 8]
=============================================初始数组:[1, 2, 3, 4, 5, 6, 9, 7, 10, 8]
基准数temp:9
初始a[j]=8
初始a[i]=9
---------------开始进行快速排序---------------
---------------开始交换---------------
交换之后的数组:[1, 2, 3, 4, 5, 6, 9, 7, 8, 10]
---------------交换结束---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 8, 7, 9, 10]
=============================================初始数组:[1, 2, 3, 4, 5, 6, 8, 7, 9, 10]
基准数temp:8
初始a[j]=7
初始a[i]=8
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
=============================================初始数组:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
基准数temp:7
初始a[j]=7
初始a[i]=7
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
=============================================初始数组:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
基准数temp:10
初始a[j]=10
初始a[i]=10
---------------开始进行快速排序---------------
排序之后的数组:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
=============================================快速排序的结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

选择排序

原理
假设有10个数,
第一轮循环,
第一个数和第二个数比较,如果第一个数大,第一个数和第二个数交换位置,否则不动;接着第一个数和第三个数比较(注意:如果上一轮中第一个数比第二个数大,则此时第一个数在第二个数的位置),如果第一个数大,第一个数和第三个数交换位置,否则不动
……
第一个数和第十个数比较,如果第一个数大,第一个数和第十个数交换位置,否则不动。第一轮循环结束,最小的数挪到了第一个数的位置,比较进行了9次。

第二轮循环,
第二个数和第三个数比较,如果第二个数大,第二个数和第三个数交换位置,否则不动
……
第二个数和第十个数比较,如果第二个数大,第二个数和第十个数交换位置,否则不动。第二轮循环结束,第二小的数挪到了第二个数的位置,比较进行了8次。
……
第九轮循环,
第九个数和第十个数比较,如果第九个数大,第九个数和第十个数交换位置,否则不动。第九轮循环结束,倒数第二小的数挪到了倒数第二个的位置,比较进行了1次。

图解



Java实现

import java.util.Arrays;public class SelectSort {public static void main(String[] args) {// TODO Auto-generated method stubint[] arr = {2,19,65,1,88,5,8,3,12};System.out.println("初始数组:"+Arrays.toString(arr));SelectSort.selectSort(arr);System.out.println("结果数组:"+Arrays.toString(arr));}public static void selectSort(int arr[]){int tmp,minindex = 0;//控制轮数for(int i=0;i<arr.length-1;i++){//控制比较次数,找出最小数minindex=i;for(int j=i;j<arr.length-1;j++){if(arr[minindex]>arr[j+1]){minindex=j+1;}}tmp=arr[minindex];arr[minindex]=arr[i];arr[i]=tmp;System.out.println("开始选择排序:"+Arrays.toString(arr));}}
}

运行结果

初始数组:[2, 19, 65, 1, 88, 5, 8, 3, 12]
开始选择排序:[1, 19, 65, 2, 88, 5, 8, 3, 12]
开始选择排序:[1, 2, 65, 19, 88, 5, 8, 3, 12]
开始选择排序:[1, 2, 3, 19, 88, 5, 8, 65, 12]
开始选择排序:[1, 2, 3, 5, 88, 19, 8, 65, 12]
开始选择排序:[1, 2, 3, 5, 8, 19, 88, 65, 12]
开始选择排序:[1, 2, 3, 5, 8, 12, 88, 65, 19]
开始选择排序:[1, 2, 3, 5, 8, 12, 19, 65, 88]
开始选择排序:[1, 2, 3, 5, 8, 12, 19, 65, 88]
结果数组:[1, 2, 3, 5, 8, 12, 19, 65, 88]

冒泡排序与快速排序的比较

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。

参考文章

冒泡排序:
https://blog.csdn.net/u011109881/article/details/80038573
https://blog.csdn.net/NathanniuBee/article/details/83413879

快速排序:
https://blog.csdn.net/Adusts/article/details/80882649
https://blog.csdn.net/qq_41247642/article/details/88967851
https://blog.csdn.net/u011109881/article/details/80038573

选择排序:
https://blog.csdn.net/u011109881/article/details/80038573
https://www.cnblogs.com/onepixel/articles/7674659.html

冒泡排序+快速排序+选择排序(图解)相关推荐

  1. js实现冒泡排序,快速排序,选择排序

    用js冒泡排序,快速排序,选择排序 1.冒泡排序 冒泡排序是比较经典的排序方法,是一种用时间换空间的排序方法.我总结了一下它的特点:(1)它的时间复杂度是:(2)每一趟相邻元素两两比较完毕就会产生最值 ...

  2. C语言排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)

    参考:C语言五大排序(桶排序,冒泡排序,选择排序,插入排序,快速排序)动态演示 作者:一只青木呀 发布时间: 2020-09-09 20:18:43 网址:https://blog.csdn.net/ ...

  3. 掌握常见的内部排序方法(插入排序,冒泡排序,选择排序,快速排序,堆排序,希尔排序,归并排序,基数排序等)...

    掌握常见的内部排序方法(插入排序,冒泡排序,选择排序,快速排序,堆排序,希尔排序,归并排序,基数排序等). 数组高级以及Arrays(掌握) 排序方法 空间复杂度 时间复杂度 稳定性 插 入 排 序 ...

  4. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  5. 常见的五种排序,冒泡排序,选择排序,插入排序,并归排序,快速排序

    冒泡排序 冒泡排序介绍: 冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法. 它重复地跑过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小)那么它就会按照大到小的 ...

  6. c语言排序(快速排序,冒泡排序,选择排序,插入排序,桶排序)

    快速排序,冒泡排序,选择排序,插入排序,桶排序 文章目录 什么是排序 快速排序 实现流程 代码 改进版快速排序代码 注意点 冒泡排序 实现流程 实现代码 选择排序 实现代码 插入排序 实现代码 桶排序 ...

  7. JS 排序算法详解(冒泡排序,选择排序,插入排序,希尔排序,快速排序)

    JS 排序算法详解(冒泡排序,选择排序,插入排序,希尔排序,快速排序) 一. 大O表示法 在进行排序算法之前,我们得先掌握一种对算法效率的表示方法,大O表示法. 我们使用大O表示法来表示算法的时间复杂 ...

  8. 【Java】八个常用的排序算法:插入排序、冒泡排序、选择排序、希尔排序 、快速排序、归并排序、堆排序和LST基数排序

    这篇文章主要介绍了Java如何实现八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 .快速排序.归并排序.堆排序和LST基数排序,需要的朋友可以参考下 本文实现了八个常用的排序算法:插入排序 ...

  9. 【C语言冒泡排序、选择排序和快速排序】

    文章目录 前言 一.冒泡排序 二.选择排序 三. 快速排序 四.代码设计与实现 代码设计 代码实现 调试结果 冒泡排序改良 延伸思考 总结 前言 本文简单介绍了C语言的冒泡排序.选择排序.快速排序,结 ...

最新文章

  1. Redis源码解析——Zipmap
  2. C#网页自动登录和提交POST信息的多种方法
  3. 基于Jedis实现Redis分片的理解
  4. sql随机查询数据语句(NewID(),Rnd,Rand(),random())
  5. 快看漫画大数据平台的模型思维与用户增长实践
  6. php设计分布图,MySQL分表实现上百万上千万记录分布存储的批量查询设计模式[图]_MySQL...
  7. ZOJ - 2955 Interesting Dart Game(鸽巢原理+完全背包)
  8. ybtoj洛谷P3268:圆的异或并(扫描线)
  9. python任务调度平台 界面_分布式任务调度平台XXL-JOB搭建教程
  10. innodb doublewrite
  11. Linux Shell 函数返回值
  12. MySQL锁系列3 MDL锁
  13. GIT 查看/修改用户名和邮箱地址
  14. AUTOCAD——多段线命令
  15. JS旋转木马图片轮播
  16. 内行人看笑话 外行人一脸懵逼
  17. 什么是纵向加密与横向隔离
  18. STM32读取DHT11中时序的问题,通过逻辑分析仪读取信号
  19. 项目笔记一-----------------iphone官网仿制
  20. 大数据的特点和快的原因

热门文章

  1. C# winform实现百度地图导航
  2. 【阿贝云】免费的云服务器,真香
  3. 上车了!AR摩托车头盔了解一下?
  4. 什么是基于模型的测试?
  5. 2022网安保研经验帖
  6. 对字符串进行信道编码C语言,【单选题】PCM编码主要用于实现模拟信号数字化,它属于( ) A. 信道编码 B. 纠错编码 C. 信源编码 D. 压缩编码...
  7. 点云公开数据集:Semantic3D
  8. 姓氏 (C++)简单贪心
  9. 新版曝光骗子公示PHP系统源码+云黑系统
  10. 7-5 手机号码 (20 分)