一、选择法排序
选择法排序指每次选择所要排序的数组中的最大值(由大到小排序,由小到大排序则选择最小值)的数组元素,将这个数组元素的值与最前面没有进行排序的数组元素的值互换。
下面以数字9、6、15、4、2为例,对这几个数字进行排序,每次交换的顺序如表所示。
代码实例
#include <stdio.h>
int main()
{
int i,j;
int a[10];
int iTemp;
int iPos;
printf("为数组元素赋值:\n");
/*从键盘为数组元素赋值*/
for(i=0;i<10;i++)
{
printf("a[%d]=",i);
scanf("%d", &a[i]);
}
/*从小到大排序*/
for(i=0;i<9;i++) /*设置外层循环为下标0~8的元素*/
{
iTemp = a[i]; /*设置当前元素为最小值*/
iPos = i; /*记录元素位置*/
for(j=i+1;j<10;j++) /*内层循环i+1到9*/
{
if(a[j]<iTemp) /*如果当前元素比最小值还小*/
{
iTemp = a[j]; /*重新设置最小值*/
iPos = j; /*记录元素位置*/
}
}
/*交换两个元素值*/
a[iPos] = a[i];
a[i] = iTemp;
}
/*输出数组*/
for(i=0;i<10;i++)
{
printf("%d\t",a[i]); /*输出制表位*/
if(i == 4) /*如果是第5个元素*/
printf("\n"); /*输出换行*/
}
return 0; /*程序结束*/
}
二、冒泡法排序
冒泡法排序指的是在排序时,每次比较数组中相邻的两个数组元素的值,将较小的数(从小到大排列)排在较大的数前面。
下面仍以数字9、6、15、4、2为例,对这几个数字进行排序,每次排序的顺序如表所示。
#include<stdio.h>
#include <iostream.h>
int main()
{
int i,j;
int a[10];
int iTemp;
printf("为数组元素赋值:\n");
/*从键盘为数组元素赋值*/
for(i=0;i<10;i++)
{
printf("a[%d]=",i);
scanf("%d", &a[i]);
}
/*从小到大排序*/
for(i=1;i<10;i++) /*外层循环元素下标为1~9*/
{
for(j=9;j>=i;j--) /*内层循环元素下标为i~9*/
{
if(a[j]<a[j-1]) /*如过前一个数比后一个数大*/
{
/*交换两个数组元素的值*/
iTemp = a[j-1];
a[j-1] = a[j];
a[j] = iTemp;
}
}
}
/*输出数组*/
for(i=0;i<10;i++)
{
printf("%d\t",a[i]); /*输出制表位*/
if(i == 4) /*如果是第5个元素*/
printf("\n"); /*输出换行*/
}
return 0; /*程序结束*/
}
三、交换法排序
交换法排序是将每一位数与其后的所有数一一比较,如果发现符合条件的数据则交换数据。首先,用第一个数依次与其后的所有数进行比较,如果存在比其值大(小)的数,则交换这两个数,继续向后比较其他数直至最后一个数。然后在使用第二个数与其后面的数进行比较,如果存在比其值大(小)的数,则交换这两个数。继续向后比较其他数直至最后一个数,直至最后一个数比较完成。
下面以数字9、6、15、4、2为例,对这几个数字进行交换法排序,每次排序的顺序如表所示。
#include <stdio.h>
int main()
{
int i,j;
int a[10];
int iTemp;
printf("为数组元素赋值:\n");
/*从键盘为数组元素赋值*/
for(i=0;i<10;i++)
{
printf("a[%d]=",i);
scanf("%d", &a[i]);
}
/*从小到大排序*/
for(i=0;i<9;i++) /*外层循环元素下标为0~8*/
{
for(j=i+1;j<10;j++) /*内层循环元素下标为i+1到9*/
{
if(a[j] < a[i]) /*如果当前值比其他值大*/
{
/*交换两个数值*/
iTemp = a[i];
a[i] = a[j];
a[j] = iTemp;
}
}
}
/*输出数组*/
for(i=0;i<10;i++)
{
printf("%d\t",a[i]); /*输出制表位*/
if(i == 4) /*如果是第5个元素*/
printf("\n"); /*输出换行*/
}
return 0; /*程序结束*/
}
四、插入法排序
插入法排序较为复杂,其基本工作原理是抽出一个数据,在前面的数据中寻找相应的位置插入,然后继续下一个数据,直到完成排序。
下面以数字9、6、15、4、2为例,对这几个数字进行插入法排序,每次排序的顺序如表所示。
#include <stdio.h>
int main()
{
int i;
int a[10];
int iTemp;
int iPos;
printf("为数组元素赋值:\n");
/*从键盘为数组元素赋值*/
for(i=0;i<10;i++)
{
printf("a[%d]=",i);
scanf("%d", &a[i]);
}
/*从小到大排序*/
for(i=1;i<10;i++) /*循环数组中元素*/
{
iTemp = a[i]; /*设置插入值*/
iPos = i-1;
while((iPos>=0) && (iTemp<a[iPos])) /*寻找插入值的位置*/
{
a[iPos+1] = a[iPos]; /*插入数值*/
iPos--;
}
a[iPos+1] = iTemp;
}
/*输出数组*/
for(i=0;i<10;i++)
{
printf("%d\t",a[i]); /*输出制表位*/
if(i == 4) /*如果是第5个元素*/
printf("\n"); /*输出换行*/
}
return 0; /*程序结束*/
}
五、折半法排序
折半法排序又称为快速排序,是选择一个中间值middle(在程序中,我们使用数组中间值),然后把比中间值小的数据放在左边,比中间值大的数据放在右边(具体的实现是从两边找,找到一对后进行交换)。然后对两边分别递归使用这个过程。
下面以数字9、6、15、4、2为例,对这几个数字进行折半法排序,每次排序的顺序如表所示。
#include <stdio.h>
void CelerityRun(int left, int right, int array[]);
int main()
{
int i;
int a[10];
printf("为数组元素赋值:\n");
/*从键盘为数组元素赋值*/
for(i=0;i<10;i++)
{
printf("a[%d]=",i);
scanf("%d", &a[i]);
}
/*从小到大排序*/
CelerityRun(0,9,a);
/*输出数组*/
for(i=0;i<10;i++)
{
printf("%d\t",a[i]); /*输出制表位*/
if(i == 4) /*如果是第5个元素*/
printf("\n"); /*输出换行*/
}
return 0; /*程序结束*/
}
void CelerityRun(int left, int right, int array[])
{
int i,j;
int middle,iTemp;
i = left;
j = right;
middle = array[(left+right)/2]; /*求中间值*/
do
{
while((array[i]<middle) && (i<right)) /*从左找小于中值的数*/
i++;
while((array[j]>middle) && (j>left)) /*从右找大于中值的数*/
j--;
if(i<=j) /*找到了一对值*/
{
iTemp = array[i];
array[i] = array[j];
array[j] = iTemp;
i++;
j--;
}
}while(i<=j); /*如果两边的下标交错,就停止(完成一次)*/
/*递归左半边*/
if(left<j)
CelerityRun(left,j,array);
/*递归右半边*/
if(right>i)
CelerityRun(i,right,array);
}
六、排序算法的比较
在前面已经介绍了5种排序方法,那么在进行数组排序时应该使用哪一种方法呢?这就应该根据需要进行选择。下面对这5种排序方法进行一下简单的比较。
(1)选择法排序
选择法排序在排序过程中共需进行n(n-1)/2次比较,互相交换n-1次。选择法排序简单、容易实现,适用于数量较小的排序。
(2)冒泡法排序
最好的情况是正序,因此只要比较一次即可;最坏的情况是逆序,需要比较n^2次。冒泡法是稳定的排序方法,当待排序列有序时,效果比较好。
(3)交换法排序
交换法排序和冒泡法排序类似,正序时最快,逆序时最慢,排列有序数据时效果最好。
(4)插入法排序
此算法需要经过n-1次插入过程,如果数据恰好应该插入到序列的最后端,则不需要移动数据,可节省时间,因此若原始数据基本有序,此算法具有较快的运算速度。
(5)折半法排序
折半法排序对于较大的n时,是速度最快的排序算法;但当n很小时,此方法往往比其他排序算法还要慢。折半法排序是不稳定的,对应有相同关键字的记录,排序后的结果可能会颠倒次序。
插入法、冒泡法、交换法排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度;在这种情况下,折半法排序反而会显得速度慢了。当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。