前面我们提到过冒泡排序的非标准版,
用的是自上而下,每一个元素都与其它元素进行比较,如果前面大于后面的,则交换它们的值,
那此时就会出现一个性能上的问题,
因为在第二层循环体内,如果发现前面的元素大于后面的元素,就会交换它们的值。
而我们知道,二层循环体执行结束后的意义就是讲最小值放到前面,至于后面数值的顺序,它的排列时无意义的。
我们在后面的循环中才会将其排序。
所以说呢,我们有没有办法,将循环体中的最小值找到,放到一层循环的位置上。不久可以了吗?
简单选择排序就可以帮我们实现这个目的
void SelectSort(SqList *L){ int i,j,min; for(i=1;i<L->length;i++){ min = i; for(j=1;j<L->length;j++){ if(L->r[min]>L->r[j]){ min = j; } } if(i!=min){ swap(L,i,min); } } }
代码中,我们用一个变量min 来 代替i的初始值,然后在二层for循环体内,如果找到比min位置中还小的值,就将那个位置赋值给min。
这样,在二层循环体结束之后,如果判断当前的min下标和初始的下标如同,则代表改动过下标min的值,此时,交换i和min的位置上的值。
下面来例子说明了,简单选择排序和冒泡排序非标准版在性能上的区别
如果我们需要排序的序列是{9,1,5,8,3,7,4,6,2}
对于从1循环到8,当i是1时,
L.r[i] = 9 ,min 开始是1,然后与j=2到9比较 L.r[min] 与L.r[j]的大小,因为j=2是最小,所以min=2.
最终交换了L.r[2]和L.r[1]的值。
注意,这里比较了8次,却只交换数据操作一次。
当i=2是,L.r[i] = 9, min = 2 经过比较,min=9,交换L.r[min]与L.r[i]的值。这样就找到了第二个位置的关键字。
如果此时,我们用的是冒泡排序标准版,那么9和5会交换,5和3会交换,3和2会交换,一共要交换3次。
这样,我们就了解了它们在性能上的差异了。
下面给出java版的代码:
public class TestBubbleSort0 { public static void main(String args[]) { int a[] = {43, 54, 12, 65, 24, 123, 65, 42, 56, 221}; int min; for(int i=0;i<a.length-1;i++){ min = i; for(int j=i+1;j<=a.length-1;j++){ if(a[min]>a[j]){ min = j; } } if(i!=min){ bubbleSort0(a, i, min); } } for (int i = 0; i < a.length ; i++) { System.out.print(a[i] + " "); } } static void bubbleSort0(int a[], int i, int j) { int temp; temp = a[i]; a[i] = a[j]; a[j] = temp; } }