标签:
冒泡排序是一种交换排序,它的基本思想是:两两比较序列中相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。它的运行过程如下(以升序排序为例):
比如待排序序列数组为:9 2 6 8 7 3 1 0 4 5,将其升序排序成序列0 1 2 3 4 5 6 7 8 9,按照上述冒泡法的运行过程有:
9 2 6 8 7 3 1 0 4 5 相邻记录关键字作比较,9>2交换得到序列:2 9 6 8 7 3 1 0 4 5
2 9 6 8 7 3 1 0 4 5 同样的,9>6,交换后:2 6 9 8 7 3 1 0 4 5
2 6 9 8 7 3 1 0 4 5 9>8 交换得到:2 6 8 9 7 3 1 0 4 5
…..
2 6 8 7 3 1 0 4 9 5 9>5 交换 得到:2 6 8 7 3 1 0 4 5 9
在经过N-1次比较后可以看到关键字最大的元素9经过升序冒泡后已经到了序列的最尾端,这个过程称为第一趟冒泡排序。接着再从序列的第一对相邻元素开始进行第二趟排序:
2 6 8 7 3 1 0 4 5 9 ——>2 6 8 7 3 1 0 4 5 9
2 6 8 7 3 1 0 4 5 9——>2 6 8 7 3 1 0 4 5 9
2 6 8 7 3 1 0 4 5 9——>2 6 7 8 3 1 0 4 5 9
….
2 6 7 3 1 0 4 8 5 9 ——>2 6 7 3 1 0 4 5 8 9
第二趟排序完成,把关键字8升到了序列倒数第二个位置。可以发现,第二趟排序的比较次数比第一趟少了一次,8与最后的9没有进行比较。
重复这个过程进行N-1趟的比较之后,可完成对整个序列的冒泡排序。
按照这个思路,相应的代码为:
void BubbleSort1(int array[],int arrayLength) { int i ,j ; for(i=0;i<arrayLength-1;++i) //进行N-1趟比较 { for(j= 1;j<arrayLength-i;++j) //每趟比较中的内循环 if(array[j]<array[j-1]) //即相邻元素之间的比较 Swap(array[j],array[i]); //反序,进行交换 } }
注意到我在写冒泡排序定义的时候,用红色字体强调了冒泡排序进行比较的是相邻的元素,如下面这段代码,在结构上虽然很像冒泡,实际上只是简单的交换排序:
void Sort(int array[],int arrayLength) { int i ,j ; for(i=0;i<arrayLength-1;++i) { for(j=i+1;j<arrayLength;++j) if(array[j]<array[i]) //这里比较的非相邻的元素。该算法不是冒泡 Swap(array[j],array[i]); } }
这种算法做了大量的无用的交换操作,效率是非常低下的。
排序算法还可以进行优化,设置一个标志域flag,如果某一趟排序发生了变换,那么flag为true。如果某一趟排序没有发生交换,则说明序列已经有序了,不必再进行继续的比较操作,此时flag为false。
{ int i ,j ; bool flag = true; for(i=0;i<arrayLength-1&&flag;++i) { flag = false; for(j= 1;j<arrayLength-i;++j) if(array[j]<array[j-1]) { Swap(array[j],array[j-1]); flag = true; //有交换,表明当前序列尚未有序,标志为ture } } }
冒泡法还有另外一种优化,即只对无序的关键字进行排序。假设有序列array={2,1,5,4,0,6,7,8,9}按升序排序,则只需对无序区{2,1,5,4,0}进行排序即可。使用一个标志来记录无序区的范围:
void BubbleSort3(int array[],int arrayLength) { int flag = arrayLength-1; while(flag>0) { for(int i = 0;i<arrayLength-1;i++) { int k = flag; flag=0; for(int j = 0;j<k;++j) if(array[j]<array[j+1]) { Swap(array[j],array[j+1]); flag=j; //记录无序区的末尾位置 } } } }
当然,这种优化情况还是有点特殊的,但序列完全反序时起不到优化作用的。
总体来说,冒泡排序的效率是较为低下在,在数据量小的情况下可以使用,否则应该选择其他的排序算法。
标签:
原文地址:http://www.cnblogs.com/QG-whz/p/4390901.html