冒泡排序、选择排序和插入排序的区别

这三种排序的时间级别:

  冒泡排序:比较 (N-1)+(N-2)+...+2+1 = N*(N-1)/2=N2/2

       交换  0——N2/2 = N2/4

       总时间 3/4*N2

  选择排序:比较 (N-1)+(N-2)+...+2+1 = N*(N-1)/2=N2/2

       交换  0——3*(N-1)=3*(N-1)/2=3/2*N

       总时间 N2/2+3/2*N

  插入排序:第一轮最多比较一次,第二轮最多比较俩次,最后一轮比较N-1次,所以最多比较N*(N-1)/2。

       复制的次数和比较的次数大致相等,但是复制消耗的时间比交换要小.

       比较 0——N*(N-1)/2=N*(N-1)/4=N2/4

       复制 0——N*(N-1)/2=N*(N-1)/4=N2/4

       总时间 N2//2

  总结:插入排序算法比冒泡快一倍,比选择排序略快一点,但这些算法都是O(N2)的时间级别。


冒泡算法思想:每次相邻元素进行比较,如果发现较小的元素在后面,就交换两个相邻的元素。

数组实例:int array[] = { 23, 63, 19, 8, 36, 48, 42 };

冒泡排序:

// 冒泡排序法

public void bubbleSort() {
// 定义临时变量
int temp = 0;
// 外层控制循环的次数
for (int i = 0; i < array.length - 1; i++) {
// 内层是比较的次数
for (int j = array.length - 1; j > i; j--) {
// 索引大的对应的数组值大于索引小的对应的数组值,需要交换,小的往上浮
if (array[j] > array[j - 1]) {
temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}

}

具体实例说明:

第一次循环:

外层循环:i=0;

内层循环:array[6]<array[5]不交换,数组顺序不变

array[5]>array[4]交换,数组顺序{ 23, 63, 19, 8, 48, 36, 42 },

array[4]>array[3]交换,数组顺序{ 23, 63, 19, 48, 8, 36, 42 },

array[3]>array[2]交换,数组顺序{ 23, 63, 48, 19, 8, 36, 42 },

array[2]<array[1]不交换,数组顺序不变,

array[1]>array[0]交换,数组顺序{ 63, 23, 48, 19, 8, 36, 42 }.

依次类推,就能得到从大到小的排序了。

运行结果:


选择排序算法思想在冒泡排序上做了优化,减少了交换次数,在首轮选择最大的数放在第一项,一轮之后第一项是有序的了,第二轮从第二项开始选择最大的数放在第二项,以此类推,直到整个数组完全有序。

选择排序:

// 选择排序算法

public void sort() {
// 对应位置的数组下标
int max;
// 定义临时变量
int temp;
for (int i = 0; i < array.length - 1; i++) {
max = i;//假设数组下标为0项是最大的,数组下标为1项是第二大的
/** 查找第 i大的数,直到记下第 i大数的位置 ***/
for (int j = i; j < array.length; j++) {
// 如果当前位置不是最大的,记录比它大的数组下标
if (array[max] < array[j]) {
max = j;// 记下较大数位置,再次比较,直到最大
}
}
/***

* 如果第 i大数的位置不在 i,则交换, 也就是排在第一个不是最大的就交换,第二大的不在第二大的位置上

                        交换 ****/

if (i != max) {
temp = array[i];
array[i] = array[max];
array[max] = temp;
}
}
}

具体实例说明:

第一次循环:

外层循环:i=0;

内层循环:array[max](array[0])<array[1],此时max=1;

array[max]和array[2]比,array[max]和array[3]比,array[max]和array[4]比,array[max]和array[5]比,array[max]和array[6]比,

相比过后array[max](array[1])此时是最大的,内层循环结束;

0!=1所以,array[0]和array[max](array[1])交换,此时数组的顺序{ 63, 23, 19, 8, 36, 48, 42 }.

依次类推,数组的顺序是从大到小排序。

运行结果:

插入排序算法思想和前俩种排序不同,插入排序在排序过程中是局部有序,随着插入项的增多,有序部分的项的位置会发生改变,而冒泡排序和选择排序每轮确定的项数的位置是永远不变的。在首轮,选择第二项作为插入项,然后取出这一项放在一个变量中,和前一项比较而且小,则前一项后移到第二项的位置,然后第二项也就是插入项放在前一项的位置,第二轮选择第三项作为插入项然后取出和前一项也就是第二项比较如果小,第二项后移到插入项,然后插入相在和第一项比较如果小,则第一项后移到第二项,插入项放在第一项,以此类推。

插入排序:

//  插入排序
public void insertSort() {
// 定义临时变量
int temp = 0;
// 外层循环控制次数
for (int i = 1; i < array.length; i++) {
// 把插入项的数值赋值给临时变量
temp = array[i];
int j = i;
// 判断前一项是否比插入项大
while (j > 0 && array[j - 1] > temp) {
array[j] = array[j - 1];
j--;
}
// 把插入项的数组值赋值给数组首项
array[j] = temp;
}

}

具体实例说明:

只取数组前4项进行说明,{23,63,19,8},第一次循环,i=1,j=1;array[0]<63,所以第一轮顺序不变,

第二次循环,i=2,j=2;array[1]>19,所以array[2]=63,内部继续循环,j=1;array[0]>19,所以array[1]=23,内部循环结束,array[0]=19.此时顺序为{19,23,63,8}.

第三次循环,i=3,j=3;array[2]>8,所以array[3]=63,内部循环继续,i=2,j=2;array[1]>8所以array[2]=23,内部继续循环,j=1;array[0]>8,所以array[1]=19,内部循环结束,array[0]=8.此时顺序为{8,19,23,63}.

运行结果:


总结:冒泡算法,每次比较如果发现较大的元素在后面,就交换两个相邻的元素。而选择排序算法的改进在于:先并不急于调换位置,先从Aarray[0]开始逐个检查,看哪个数最大就记下该数所在的位置j,等一躺扫描完毕,再把Array[max](max=j)和A[0]对调,这时Array[0]到Array[6]中最大的数据就换到了最前面的位置。所以,选择排序每扫描一遍数组,只需要一次真正的交换,而冒泡可能需要很多次,比较的次数是一样的。插入排序算法比冒泡快一倍,比选择排序略快一点。








猜你喜欢

转载自blog.csdn.net/qq_39380737/article/details/80907396