三个排序算法
1. vb三种基本排序算法
三种基本排序算法(与哪种编程语言无关):
冒泡排序算法、选择排序算法、插入排序算法
2. 一文详解三种时间复杂度为O(N)的排序算法
导读数据结构和算法这个东西,如果你不去学,可能真的这辈子都用不到,也感受不到它的好。但是一旦掌握,你就会常常被它的强大威力所折服。之前你可能需要费很大劲儿来优化的代码,需要花很多心思来设计的架构,用了数据结构和算法之后,很容易就可以解决了。
排序是一个非常经典的问题,它以一定的顺序对一个数组(或一个列表)中的项进行重新排序(可以进行比较的,例如整数,浮点数,字符串等)。
有许多不同的排序算法,每个都有其自身的优点和局限性。
基于比较的排序算法:
比较数组的元素,并决定是否交换它们的位置。
BUB-冒泡排序
SEL-选择排序
INS-插入排序
MER-归并排序(递归实现)
QUI-快速排序(递归实现)
R-Q-随机快速排序(递归实现)
不基于比较的排序算法:
COU-计数排序
RAD-基数排序
我们来逐一破解这些排序算法。
本文分析冒泡排序、选择排序和插入排序。
一、冒泡排序假设数组arr长度为$N$,冒泡排序的过程为:
在arr[0~N-1]范围上:
arr[0]和arr[1],谁大谁来到1位置;
arr[1]和arr[2],谁大谁来到2位置;
[N-2]和arr[N-1],谁大谁来到N-1位置;
在arr[0~N-2]范围上,重复上面的过程,但最后一步是arr[N-3]和arr[N-2],谁大谁来到N-2位置;
在arr[0~N-3]范围上,重复上面的过程,但最后一步是arr[N-4]和arr[N-3],谁大谁来到N-3位置;
…
最后在arr[0~1]范围上,重复上面的过程,但最后一步是arr[0]和arr[1],谁大谁来到1位置。
整个过程将最大的元素移动到最右侧,也就是最大的元素浮动到最右边,像冒泡一样。
如图所示:
如图展示了第1趟排序的过程。
自己会动的才是好图:
代码实现:
publicclassBubbleSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){if(arr==null||arr.length<2){return;}//想要让0~i位置上有序,i一开始在数组的最大索引位置上,每比完1次,减1for(inti=arr.length-1;i>0;i--){//0~i//0~(i-1)//0~(i-2)...//0~1for(intj=0;j<i;j++){if(arr[j]>arr[j+1]){inttemp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}}System.out.println("0~"+i+"位置比较结果:"+Arrays.toString(arr));}}}执行结果:
第0趟比较结果:[15,13,17,6,18,15,9,20]第1趟比较结果:[13,15,6,17,15,9,18,20]第2趟比较结果:[13,6,15,15,9,17,18,20]第3趟比较结果:[6,13,15,9,15,17,18,20]第4趟比较结果:[6,13,9,15,15,17,18,20]第5趟比较结果:[6,9,13,15,15,17,18,20]第6趟比较结果:[6,9,13,15,15,17,18,20]第7趟比较结果:[6,9,13,15,15,17,18,20]时间复杂度的计算:
比较和交换需要一个以常量为界的时间,我们称之为$c$。
BubbleSort中有两个嵌套循环。
外循环正好运行$N$次迭代。但内部循环运行变得越来越短:
当i=0,(N-1)次迭代(比较和可能交换)时。
当i=1,(N-2)次迭代时,...
当i=(N-2)时,1次迭代,
当i=(N-1),0迭代.
因此:
$$总迭代次数=(N-1)+(N-2)+...+1+0=N×(N-1)/2$$
计算总时间:$$总时间=c×N×(N-1)/2=O(N?)$$
二、选择排序给定$N$个元素和L=0的数组,选择排序过程为:
在[L...N-1]范围内找出最小项X的位置,
用第L项交换X,
将下限L增加1并重复步骤1直到L=N-2。
手绘选择排序过程:
动画演示:
代码实现:
publicclassSelectionSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){for(inti=0;i<arr.length-1;i++){//目的:找到最小值的位置,并将该位置的数与i位置的数交换intminIndex=i;for(intj=i+1;j<arr.length;j++){minIndex=arr[j]>arr[minIndex]?minIndex:j;}//找到最小值后,与i位置的数交换inttemp=arr[i];arr[i]=arr[minIndex];arr[minIndex]=temp;System.out.println("第"+i+"~"+(arr.length-1)+"位置上的最小值索引为"+minIndex+",最小值为:"+arr[minIndex]+",本次排序结果:"+Arrays.toString(arr));}}}运行结果:
第0~7位置上的最小值索引为4,最小值为:18,本次排序结果:[6,15,13,17,18,20,15,9]第1~7位置上的最小值索引为7,最小值为:15,本次排序结果:[6,9,13,17,18,20,15,15]第2~7位置上的最小值索引为2,最小值为:13,本次排序结果:[6,9,13,17,18,20,15,15]第3~7位置上的最小值索引为7,最小值为:17,本次排序结果:[6,9,13,15,18,20,15,17]第4~7位置上的最小值索引为6,最小值为:18,本次排序结果:[6,9,13,15,15,20,18,17]第5~7位置上的最小值索引为7,最小值为:20,本次排序结果:[6,9,13,15,15,17,18,20]第6~7位置上的最小值索引为6,最小值为:18,本次排序结果:[6,9,13,15,15,17,18,20]总结一下选择排序的过程:
arr[0~N-1]范围上,找到最小值所在的位置,然后把最小值交换到0位置。
arr[1~N-1]范围上,找到最小值所在的位置,然后把最小值交换到1位置。
arr[2~N-1]范围上,找到最小值所在的位置,然后把最小值交换到2位置。
…
arr[N-1~N-1]范围上,找到最小值位置,然后把最小值交换到N-1位置。
估算:很明显,如果arr长度为N,每一步常数操作的数量,如等差数列一般,所以有:
$$总的常数操作数量=a(N?)+bN+c(a、b、c都是常数)$$
所以选择排序的时间复杂度为$O(N?)$。
三、插入排序这个算法比较好理解,想象一下平时打扑克牌,我们很自然的就会把一张牌和手里的牌挨个比较一下,并把它插入到合适的位置。
过程:
想让arr[0~0]上有序,这个范围只有一个数,当然是有序的;
想让arr[0~1]上有序,所以从arr[1]开始往前看,如果arr[1]<arr[0],就交换。否则什么也不做;
…
想让arr[0~i]上有序,所以从arr[i]开始往前看,arr[i]这个数不停向左移动,一直移动到左边的数字不再比自己大,停止移动;
最后一步,想让arr[0~N-1]上有序,arr[N-1]这个数不停向左移动,一直移动到左边的数字不再比自己大,停止移动。
估算时发现这个算法流程的复杂程度,会因为数据状况的不同而不同。
如果某个算法流程的复杂程度会根据数据状况的不同而不同,那么必须要按照最差情况来估计。
很明显,在最差情况下,如果arr长度为N,插入排序的每一步常数操作的数量,还是如等差数列一般。
所以有:
$$总的常数操作数量=a(N?)+bN+c(a、b、c都是常数)$$
因此插入排序排序的时间复杂度为$O(N?)$。
代码实现:
publicclassInsertionSort{publicstaticvoidmain(String[]args){int[]arr={18,15,13,17,6,20,15,9};sort(arr);}publicstaticvoidsort(int[]arr){if(arr==null||arr.length<2){return;}//想让0~i位置上有序,从i位置往前看,一直到左边的数不比自己大了,停止往左看for(inti=1;i<arr.length;i++){//j=i表示从i位置开始,j--表示往前看for(intj=i;j>0;j--){if(arr[j]<arr[j-1]){inttemp=arr[j-1];arr[j-1]=arr[j];arr[j]=temp;}}System.out.println("从"+i+"位置往前看,直到左边的数不比自己大,本次结果:"+Arrays.toString(arr));}}}运行结果:
从1位置往前看,直到左边的数不比自己大,本次结果:[15,18,13,17,6,20,15,9]从2位置往前看,直到左边的数不比自己大,本次结果:[13,15,18,17,6,20,15,9]从3位置往前看,直到左边的数不比自己大,本次结果:[13,15,17,18,6,20,15,9]从4位置往前看,直到左边的数不比自己大,本次结果:[6,13,15,17,18,20,15,9]从5位置往前看,直到左边的数不比自己大,本次结果:[6,13,15,17,18,20,15,9]从6位置往前看,直到左边的数不比自己大,本次结果:[6,13,15,15,17,18,20,9]从7位置往前看,直到左边的数不比自己大,本次结果:[6,9,13,15,15,17,18,20]原文:juejin.cn/post/7128721614144798750
3. python常见的三种列表排序算法分别是什么
排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个关键字有序的序列。那么python列表排序算法有哪些?本文主要为大家讲述python中禅棚经常用的三种排序算法:冒泡排序、插入排序和选择排序。
1、冒泡排序
冒泡排序,Bubble
Sort,是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢浮到数列的顶端。
2、插入排序
插戚袭差入排序,Insertion
Sort,是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,在从后向前的扫描过程中,需要把已排序元素逐步向后挪位,为最新元素提供插入空间。
3、选择高皮排序
选择排序,Selection
Sort,是一种简单直观的排序算法。它的工作原理如下:首先在未排序序列中找到最小、最大元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小、最大元素。放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
4. python常见的三种列表排序算法分别是什么
python中有两种排序方法,list内置sort()方法或者python内置的全局sorted()方法二者区别为:sort()方法对list排序会修改list本身,不会返回新list。sort()只能对list进行排序。sorted()方法会返回新的list,保留原来的list。
先说reverse,这个很简单,就是指出是否进行倒序排序:一般情况下,1排在2的前面,而倒序则相反。key参数:一般它是一个函数,它接受列表中每一个元素,返回一个可用用于比较的值。
在Python中,Python算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。冒泡排序冒泡排序也是一种简单直观的排序算法。
③对所有两个小数列重复第二步,直至各区间只有一个数。排序演示算法实现希尔排序介绍希尔排序(ShellSort)是插入排序的一种,也是缩小增量排序,是直接插入排序算法的一种更高效的改进版本。
排序算法是《数据结构与算法》中最基本的算法之一。排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。