1. 选择排序:
选择排序是一种很简单直观的排序方法,就是在未排序的数据中挑选出最大或者最小的元素,存放到已排序数据的末尾。
简单的讲,就是每次都把最大或者最小的数据挑选出来,然后依次组成新的序列。
假设有数据{1,4,6,8,3,4,0,2,14},要按照从大到小进行排序
那么我们在第一次循环中,从第一个数据‘1’开始比较,最后挑选出最大‘14’,放到数组的第一个索引处,在第二次循环中,从第二个数据开始比较,挑选出最大的‘8’,以此类推。
显而易见,我们每进行一次排序,对比的数据就会少一个。
C语言代码实现:
void selectSort(int anData[], int nSize)
{
int i = 0;
int j = 0;
int nMax = 0;
int nTemp = 0;
for(i=0; i<nSize; i++)
{
nMax = i;
for(j=i+1; j<nSize; j++)
{
if(anData[j] > anData[nMax])
{
nMax = j;
}
}
//相同则省去替换的过程
if(nMax != i)
{
nTemp = anData[i];
anData[i] = anData[nMax];
anData[nMax] = nTemp;
}
}
}
优化:选择排序的优化空间不大,像代码中减少交换次数就是一种优化方法。
时间复杂度分析:选择排序的比较次数是可计算的:n+(n-1)+(n-2)+……+1 = n(n-1)/2;
选择排序的交换次数是0到(n-1)次,最好的情况就是已经排好序,交换0次,最差的情况是逆序,交换n-1次。
所以选择排序的时间复杂度是O(n^2)
2.冒泡排序
冒泡排序就是字面上的意思,依次比较相邻的元素,如果顺序错了就进行交换,直到将最大或者最小的数据冒泡到未排序数据的最前端或者最后端,这个过程类似于一个泡泡不停晚上冒,所以叫冒泡排序
假设有数据{1,4,6,8,3,4,0,2,14},要按照从大到小进行排序
题目要求从大到小排序,那么我们可以选择将最小的冒泡到最后面,也可以选择将最大的冒泡到最前面,我们采用第一种方法。
第一次循环:1,4比较,1比4小,交换;
1,6比较,1比6小,交换;
。。。。。。
以此类推
第一次循环结束后,数据应为{4,6,8,3,4,0,2,14,1}
第二次循环就是把第二小的数据冒泡到倒数第二的位置。
C语言代码实现:
void bubbleSort(int anData[], int nLen)
{
int i = 0;
int j = 0;
int nTemp = 0;
bool bFlag = false;
for(i=0; i<nLen-1; i++)
{
bFlag = false;
for(j=0; j<nLen-i-1; j++)
{
if(anData[j] < anData[j+1])
{
nTemp = anData[j];
anData[j] = anData[j+1];
anData[j+1] = nTemp;
bFlag = true;
}
}
//优化,如果Flag为false,证明这一轮没有发生数据交换,排序完成
if(!bFlag)
{
break;
}
}
}
优化:冒泡排序有一定程度的优化空间,如果冒泡排序过程中后半部分的数据本身是有序的,那么就可以及时停止以节约时间。如果不进行优化,冒牌排序花费的时间比选择排序要多,因为选择排序交换的次数比较少
时间复杂度分析:
最优时间复杂度,如果数列本身有序,那么只需循环比较n-1次,时间复杂度为O(n),此时交换次数为最小0
最差时间复杂度,如果数列逆序,那么所有循环都要一次走完,时间复杂度为O(n^2),此时交换次数也达到最大,与比较次数相同,都是n(n-1)/2;