O(N2)的三种排序-- 冒泡、选择、插入(java代码)
来源:互联网 发布:绝地求生加速器 知乎 编辑:程序博客网 时间:2024/05/17 02:47
- 1冒泡排序
- 1原理
- 2代码
- 3复杂度
- 2选择排序
- 1原理
- 2代码
- 3复杂度
- 3插入排序
- 1原理
- 2代码
- 3复杂度
- 4三个排序算法的小结与比较
- 1冒泡排序
1、冒泡排序
1)原理
a、比较相邻两个元素
b、如果满足交换要求(视排序规定而定,本文均按照从左到右、从小到大排序),则交换位置
c、向后移动一位,回到a步骤继续
在算法执行时,最大的数据项总是“冒泡”到数组的最后端,因此被称为冒泡排序。
2)代码
//冒泡排序public void BubbleSort(long[] a){ int out, in; int nElems = a.length; System.out.println("排序前: "); display(a); for (out =nElems-1; out>1; out -- ){ //外层for是控制冒泡的总体次数 //out>1是因为之前的n-2次排序是有序的,所以最后一个元素无需再排序即为有序 for(in = 0; in<out; in++){//内层则是冒泡的一次过程 if( a[in] > a[in + 1]){ //相邻两数之间进行比较,如果条件成立,则交换两数 swap(a, in, in+1); }// end of if }// end of for(in) System.out.print(nElems - out+":"); display(a); }//end of for(out)}//end of BubbleSort
实际上,使用swap函数来交换式为了让程序更加直观,调用swap函数会增加开销,所以在实际使用中,可以视情况而定将交换过程直接写在判断语句块中。
测试结果:
现在测试冒泡排序:排序前: 5 4 1 3 6 8 2 9 0 7 1:4 1 3 5 6 2 8 0 7 9 2:1 3 4 5 2 6 0 7 8 9 3:1 3 4 2 5 0 6 7 8 9 4:1 3 2 4 0 5 6 7 8 9 5:1 2 3 0 4 5 6 7 8 9 6:1 2 0 3 4 5 6 7 8 9 7:1 0 2 3 4 5 6 7 8 9 8:0 1 2 3 4 5 6 7 8 9 运行时间为:4毫秒
3)复杂度
假设数组中有N个数据项,那么第一趟排序进行了N-1次比较,第二趟进行了N-2次比较,以此类推,可以得到:
(N-1)+(N-2)+(N-3)+....+1=N*(N-1)/2
而交换次数显然少于比较的次数,得出结论,冒泡排序运行需要O(n2)时间级别。
2、选择排序
1)原理
注:依旧是从左到右从小到大排序
a、从数组无序部分左到右,元素依次与最小值比较(初始的最小值为第一个元素,即标志flag为0),若元素比当前最小值小,则更新标志flag为当前最小的元素的下标
b、遍历完之后,将a[flag]元素与有序部分的后一个元素交换
c、回到步骤a直至数组全部有序
2)代码
public void SelectSort(long[] a){ int nElems = a.length; int out, in,min; System.out.println("排序前: "); display(a); for(out=0; out<nElems-1; out++){ min = out; //记录最小值的下标 for(in=out+1; in<nElems; in++){ if(a[in] < a[min]){ min = in; }//end of if }//end of for(in) if(min != out){ //减少交换次数,消耗的时间更少 swap(a,out,min); } System.out.print((out+1)+":"); display(a); }//end of for(out)}//end of SelectSort
测试结果:
现在测试选择排序:排序前: 5 4 1 3 6 8 2 9 0 7 1:0 4 1 3 6 8 2 9 5 7 2:0 1 4 3 6 8 2 9 5 7 3:0 1 2 3 6 8 4 9 5 7 4:0 1 2 3 6 8 4 9 5 7 5:0 1 2 3 4 8 6 9 5 7 6:0 1 2 3 4 5 6 9 8 7 7:0 1 2 3 4 5 6 9 8 7 8:0 1 2 3 4 5 6 7 8 9 9:0 1 2 3 4 5 6 7 8 9 运行时间为:3毫秒
3)复杂度
a、首先,在选择排序中,下标小于等于out的位置的数据项总是有序的
b、选择排序和冒泡排序执行了相同次数的比较,但是交换次数更少。
c、虽然选择和冒泡一样,复杂度都是O(n2),但是当N值较小时,而且交换时间级比比较时间级大得多时,选择排序还是要快得多的
3、插入排序
1)原理
a、局部有序:在冒泡和选择排序中,数据项在某个时刻是完全有序的,而在插入排序中,某组数据仅仅是局部有序的
b、被标记的元素:在这个元素的左侧(依据本文的情况)是有序的,从这个元素开始之后的元素是尚未被排序的。
c、插入排序:从被标记元素开始将其按照顺序插入前面的有序序列。被标记的元素依次与前面的有序的元素比较,若有序元素比该标记大,则向右移动一位,直到有序序列中的元素不大于被标记元素或数组到头。然后将这个被标记的元素插入相应位置
2)代码
public void InsertSort(long[] a){ //具有局部有序的特征 //被标记的元素(比如,规定被标记的元素右边是无序的,其左边是有序的 int out,in; int nElems=a.length; System.out.println("排序前: "); display(a); for(out = 1; out<nElems; out++){ long tmp = a[out];//tmp就是标记元素 in = out; while(in >0 && a[in-1] >= tmp){ //每一趟循环将把比标记元素大的元素后移一位,比较跟移位同步进行,节省了时间 //当in=0或遇到比标记元素小的元素时跳出循环,此时in即为标记元素在有序序列的位置 a[in] = a[in-1]; System.out.print("被标记的元素为="+tmp+"内循环(比较的有序元素) i="+in+":"); display(a); in--; } a[in] = tmp;//插入被标记元素 System.out.print(out+":"); display(a); }//end of for(out)}//end of InsertSort
测试结果
现在测试插入排序:排序前: 5 4 1 3 6 8 2 9 0 7 被标记的元素为4;比较的有序元素> i=1:5 5 1 3 6 8 2 9 0 7 1:4 5 1 3 6 8 2 9 0 7 被标记的元素为1;比较的有序元素> i=2:4 5 5 3 6 8 2 9 0 7 被标记的元素为1;比较的有序元素> i=1:4 4 5 3 6 8 2 9 0 7 2:1 4 5 3 6 8 2 9 0 7 被标记的元素为3;比较的有序元素> i=3:1 4 5 5 6 8 2 9 0 7 被标记的元素为3;比较的有序元素> i=2:1 4 4 5 6 8 2 9 0 7 3:1 3 4 5 6 8 2 9 0 7 4:1 3 4 5 6 8 2 9 0 7 5:1 3 4 5 6 8 2 9 0 7 被标记的元素为2;比较的有序元素> i=6:1 3 4 5 6 8 8 9 0 7 被标记的元素为2;比较的有序元素> i=5:1 3 4 5 6 6 8 9 0 7 被标记的元素为2;比较的有序元素> i=4:1 3 4 5 5 6 8 9 0 7 被标记的元素为2;比较的有序元素> i=3:1 3 4 4 5 6 8 9 0 7 被标记的元素为2;比较的有序元素> i=2:1 3 3 4 5 6 8 9 0 7 6:1 2 3 4 5 6 8 9 0 7 7:1 2 3 4 5 6 8 9 0 7 被标记的元素为0;比较的有序元素> i=8:1 2 3 4 5 6 8 9 9 7 被标记的元素为0;比较的有序元素> i=7:1 2 3 4 5 6 8 8 9 7 被标记的元素为0;比较的有序元素> i=6:1 2 3 4 5 6 6 8 9 7 被标记的元素为0;比较的有序元素> i=5:1 2 3 4 5 5 6 8 9 7 被标记的元素为0;比较的有序元素> i=4:1 2 3 4 4 5 6 8 9 7 被标记的元素为0;比较的有序元素> i=3:1 2 3 3 4 5 6 8 9 7 被标记的元素为0;比较的有序元素> i=2:1 2 2 3 4 5 6 8 9 7 被标记的元素为0;比较的有序元素> i=1:1 1 2 3 4 5 6 8 9 7 8:0 1 2 3 4 5 6 8 9 7 被标记的元素为7;比较的有序元素> i=9:0 1 2 3 4 5 6 8 9 9 被标记的元素为7;比较的有序元素> i=8:0 1 2 3 4 5 6 8 8 9 9:0 1 2 3 4 5 6 7 8 9 运行时间为:8毫秒
3)复杂度
第一趟比较最多需要1次,第二趟最多2次,以此类推,有
1+2+3+...+(N-1)=N*(N-1)/2
而在发现插入点之前,平均只有数据量的一半进行了比较,所有又得到比较次数为
N*(N-1)/4
复制移动数据的次数大致等于比较的次数,然而复制移动与交换的时间消耗不同,所以插入排序虽然时间复杂度是O(N2)级别的,但是要比冒泡排序快一倍,比选择排序略快一些(PS:测试结果中由于加入了很多输出语句,所以实际运行时间较多)。
4、三个排序算法的小结与比较
- O(N2)的三种排序-- 冒泡、选择、插入(java代码)
- Java三种常见的排序算法:冒泡,选择,插入
- 数据结构 三种简单的排序(插入、选择、冒泡)
- 排序的三种方式(冒泡,插入,和选择)
- 改进版的冒泡排序(O(n2))
- Java-数组的三大排序方法(冒泡排序,选择排序,插入排序)
- 三种简单排序用java实现(选择排序,冒泡排序,插入排序)
- 001-简单的java代码实现几种排序算法(插入,快速,冒泡,选择)
- 复杂度为O(n2)的选择排序(1)
- 复杂度为O(n2)的选择排序(1)
- 复杂度为O(n2)的选择排序
- 直接插入排序(O(n2))
- 三种简单排序的实现(冒泡排序,选择排序,插入排序 )
- 简单选择排序(O(n2))
- java:三种经典大排序汇总,冒泡,插入,选择
- 冒泡,选择,插入,时间复杂度O(n2)算法感悟(此博文属于对于排序过程有大概了解的同学)
- 三种基础排序(冒泡、选择、插入排序)
- 三种基本排序(冒泡,选择,插入)
- 【POJ3261】Milk Patterns【后缀数组】【二分】
- getDay
- hdu acm 1853 Cyclic Tour
- Linux制作通用运行jar运行文件
- BZOJ 1067 & Interval_Tree
- O(N2)的三种排序-- 冒泡、选择、插入(java代码)
- sprintf函数的用法
- 安装numpy,scipy,matplotlib的好去处
- Redis入门很简单之一【简介与环境搭建】
- 电脑装机的十大误区,你中招了吗?
- BZOJ 1121 & science
- LayoutInflater作用
- Redis入门很简单之二【常见操作命令】
- POJ 1845 Sumdiv (大数据因子和)