第三节 交换排序
交换排序是指在排序过程中,主要是通过待排序记录序列中元素间关键字的比较,与存储位置的交换来达到排序目的一类排序方法。
1. 冒泡排序
1.1 冒泡排序的基本思想
冒泡排序是交换排序中一种简单的排序方法。它的基本思想是对所有相邻记录的关键字值进行比效,如果是逆顺(a[j]>a[j+1]),则将其交换,最终达到有序化。其处理过程为:
(1)将整个待排序的记录序列划分成有序区和无序区,初始状态有序区为空,无序区包括所有待排序的记录。
(2)对无序区从前向后依次将相邻记录的关键字进行比较,若逆序将其交换,从而使得关键字值小的记录向上"飘浮"(左移),关键字值大的记录好像石块,向下"堕落"(右移)。
每经过一趟冒泡排序,都使无序区中关键字值最大的记录进入有序区,对于由n个记录组成的记录序列,最多经过n-1趟冒泡排序,就可以将这n个记录重新按关键字顺序排列。
1.2 冒泡排序算法
原始的冒泡排序算法
对由n个记录组成的记录序列,最多经过(n-1)趟冒泡排序,就可以使记录序列成为有序序列,第一趟定位第n个记录,此时有序区只有一个记录;第二趟定位第n-1个记录,此时有序区有两个记录;以此类推,算法框架为:
for(i=n;i>1;i--)
{ 定位第i个记录;}
若定位第i个记录,需要从前向后对无序区中的相邻记录进行关键字的比较,它可以用如下所示的语句实现。
for(j=1;j< =i-1;j++)
if (a[j].key>a.[j+1].key)
{temp=a[j];a[j]=a[j+1];a[j+1]=temp;}
下面给出完成的冒泡排序算法:
void BubbleSort1 (DataType a,int n)
{
for (i=n;i>1;i--)
{ for (j=1;j<=i-1;j++)
if(a[j].key>a.[j+1].key)
{ temp=a[j];a[j]=a[j+1];a[j+1]=temp;}
}
}
改进的冒泡排序算法
在冒泡排序过程中,一旦发现某一趟没有进行交换操作,就表明此时待排序记录序列已经成为有序序列,冒泡排序再进行下去已经没有必要,应立即结束排序过程。
改进的冒泡排序算法:
void BubbleSort2 (DataType a,int n)
{
for (i=n;i>1;i--)
{
exchange=0;
for (j=1;j<=i-1;j++)
if (a[j].key>a.[j+1].key)
{ temp=a[j];a[j]=a[j+1];a[j+1]=temp; exchange=1;}
if (exchange==0) break;
}
}
进一步地改进冒泡排序算法
在前面给出的冒泡排序算法的基础上,如果我们同时记录第i趟冒泡排序中最后一次发生交换操作的位置m(m<=n-i),就会发现从此位置以后的记录均已经有序,即无序区范围缩小在a[1]至a[m]之间,所以在进行下一趟排序操作时,就不必考虑a[m+1]至a[n]范围内的记录了,而只在a[1]至a[m]范围内进行。
完整的算法:
void BubbleSort3 (DataType a,int n)
{
last=n-1;
for (i=n;i>1;i--)
{ exchange=0;
m=last; //初始将最后进行记录交换的位置设置成i-1
for (j=1;j<=m;j++)
if (a[j].key>a.[j+1].key)
{ temp=a[j];a[j]=a[j+1];a[j+1]=temp;exchange=1;
last=j; //记录每一次发生记录交换的位置
}
if (exchange==0)break;
}
}
冒泡排序比较简单,当初始序列基本有序时,冒泡排序有较高的效率,反之效率较低;其次冒泡排序只需要一个记录的辅助空间,用来作为记录交换的中间暂存单元;冒泡排序是一种稳定的排序方法。