交换排序是通过交换记录在表中的位置来实现排序的。交换排序的思想是:两两比较带排记录的关键字,一旦发现两个记录的次序与排序要求相逆,则交换这两个记录的位置,直到表中没有逆序为止。
冒泡排序:对R[0]~R[n-1]这n个记录的冒泡排序过程是:第一趟从第0个记录R[0]开始到第n个记录R[n-1]为止,对n-1对相邻的两个记录进行两两比较,若与排序要求相逆,则交换两者位置,这样经过一趟的比较、交换之后,具有最大关键值的记录就被交换到末尾R[n-1]位置上。第二趟从第0个记录R[0]开始到第n-2个记录R[n-2]为止继续重复上述的比较与交换,这样具有次大关键字的记录就被交换到R[n-2]的位置上。如此重复,经过n-1趟这样的比较和交换之后,R[0]~R[n-1]这n个记录议案关键字有序。这个排序过程就像一个个往上(往右)冒泡的气泡,最轻的气泡先冒上来(到达R[n]位置),较重的气泡后冒上来,因此形象的称之为冒泡排序。
冒泡排序最多进行n-1趟,在某趟的两两记录关键字的比较中,如果一次交换都未发生,则表明R[0]~R[n-1]中的记录已经有序,这时可结束排序过程。
冒泡排序算法如下:
#include <stdio.h>
void BubbleSort ( int array[] ,int n);
int main()
{
int array[10] = {35,12,89,0,87,89,63,654,32,2}, i;
BubbleSort(array,10);
for (i = 0; i < 10; i++)
{
printf("%d ", array[i]);
}
return 0;
}
void BubbleSort (int array[] ,int n)
{
int i,j,swap;
for (i = 0; i < n-1; i++) //进行n-1趟排序
{
swap = 0; //设置交换变量
for(j = 0; j < (n-1)-i; j++) //对R[0]~R[n-i]记录进行两两排序
{
if(array[j] > array[j+1]) //如果左边数大于右边数则交换位置
{
swap = array[j];
array[j] = array[j+1];
array[j+1] = swap;
}
}
if (swap == 0) //swap==0说明本趟没有交换发生则结束排序(已经排好)
break;
printf("\n");
}
}
排序过程示意图:
我们加上相应的printf语句看结果与我们预期是否一致:
上述冒泡排序算法是从左向右进行冒泡排序的,假定关键字越大,气泡越轻。当然我们也可以参考此算法设计出从右往左的排序算法。
从空间效率上看,冒泡只用了一个辅助单元;从时间效率上看,最好的情况是待排序列已经全部有序。这样冒泡排序在第一趟中排序过程中就没有发生交换,所以一趟结束之后即排序结束。也即,只在第一趟中进行了n-1次比较。最坏的情况是待排序记录按逆序排序,所以共需进行n-1趟排序,且第i趟需要进行n-1次比较。所以:
总比较次数 = ∑(n - i)=1/2n(n-1)
时间复杂度为O(n²),交换记录的次数与比较记录的次数相同,最坏的情况也是发生在待排序记录按逆序排列时。
但是,当具有n个记录的待排序列已经基本有序,但是最小关键字记录位于序列最后,这时仍需要n-1次排序,这样不免降低了排序的效率。因此我们可以考虑双向冒泡排序方法来解决这一问题。