1、冒泡排序
相邻的数据进行交换。如果有n个数,则需要比较n-1次,每次比较后,较大的数都会排到后面(下面),故以后相邻的数据之间可以少比较一次。当数据之间没有再进行交换了,则停止排序。故可以用do…while…来实现。
时间复杂度:O(N^2)。稳定。{
bool changeFlag;
do{
changeFlag = false;
for(int i = 1; i < n; i++){
if(a[i] < a[i-1]){
swap(a[i], a[i-1]);
changeFlag = true;
}
}
}while(changeFlag);
}
2、插入排序
从左到右一组数,除第一个数外(故n个数,只需比较n-1次),依次取出与其左面的数进行比较,若小于相邻的左边的数,则将相邻的左边的数向右一个位置,直到其不小于其相邻的左边的数,此时,找到了要插入的位置。注意,在进行比较之前,需要将待排序的数复制一份,防止在移位的时候,将待排序的数覆盖。
时间复杂度:O(N^2)。稳定。
插入排序代码:
void sort(int* a, int n)
{
int i,j;
for(i = 1; i < n; i++)
{
int temp = a[i];
for(j = i; j > 0 && temp < a[j-1]; j--)
a[j] = a[j-1];
a[j] = temp;
}
}
3、选择排序
典型的例子是将扑克牌无序的摆放,每次从中选一个最小的,依次将其排序。则第i次只需对剩余的n-i个数进行排序。现将当前的第i个数设为最小,然后依次的与当前值进行比较,遇到更小的值则更新此最小值,直到找到剩余n-i个数的最小值,然后将最小值与第i个位置上的数进行交换。因为最后一个数肯定是最大的,不需要在进行比较,因此进行了n-1趟比较。
时间复杂度:O(N^2)。不稳定。
选择排序代码:
void sort(int* a, int n)
{
for(int i=0; i < n-1; i++)
{
int min = i;
for(int j = i+1; j < n; j++)
{
if(a[j] < a[min])
min = j;
}
swap(a[min],a[i]);
}
}
4、快速排序
算法思路:
- 找分界值(一般取首元素或者中间元素)
- 分组即划分子表,小于分界值的元素靠左边,大于分界值的元素靠右边
- 将小于分界值即左边的元素中最右边的元素与分界值进行交换
- 对分界值左右两组子表再进行排序
- 两步递归
- 结束:左右元素个数均不超过一个,直接完成
{
if(n <= 1) return;
if(n == 2){
if(a[1] < a[0]) swap(a[1], a[0]);
return;
}
swap(a[n/2], a[0]);
int bounds = a[0];
int* L = a+1;
int* R = a+n-1;
while(L<R){
while(L<R && *L<bounds)
++L;
while(a<R && !(*R<bounds))
--R;
if(L < R) swap(*L, *R);
}
if(*R < bounds) swap(*R, a[0]);
sort(a, R-a);
sort(R+1, n-1-(R-a));
}
5、归并排序
归并排序的关键是将两个排好序的文件组合成一个较大的有序文件。
快速排序是一个不断划分排序的过程,类似于化整为零。而归并排序则是先化整为零在化零为整,是分治算法的典型应用。其子过程包括划分子表和合并子表。
归并操作思路:
- 申请一段辅助空间,其大小与需要进行排序的文件大小相同,即空间复杂度为O(n);
- 将带排序的文件一分为二,将其视作两个子表,将这两个子表按照元素的大小依次放入辅助空间中;
- 归并操作完成;
划分子表操作:
- 将待排序文件一分为二,通过两个递归对待排序数据元素进行二分;
- 两个递归后面紧跟着一个归并操作;
- 递归终止的条件为待排序文件的首尾关键字(索引)相等。
时间复杂度:O(NlogN)。稳定。
using namespace std;
void Merge(int sourceArr[], int tempArr[], int startIndex, int midIndex, int endIndex)
{
int i = startIndex, j = midIndex+1, k = startIndex;
while(i != midIndex+1 && j != endIndex+1)
{
if(sourceArr[i] < sourceArr[j])
tempArr[k++] = sourceArr[i++];
else
tempArr[k++] = sourceArr[j++];
}
while(i != midIndex+1)
tempArr[k++] = sourceArr[i++];
while(j != endIndex+1)
tempArr[k++] = sourceArr[j++];
for(i=startIndex; i<=endIndex; i++)
sourceArr[i] = tempArr[i];
}
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)
{
int midIndex;
if(startIndex < endIndex)
{
midIndex = (startIndex+endIndex)/2;
MergeSort(sourceArr, tempArr, startIndex, midIndex);
MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
}
}
int main()
{
int a[8] = {50,10,20,30,70,40,80,60};
int b[8];
MergeSort(a,b,0,7);
for(int i = 0; i < 8; i++)
cout << a[i] << ' ';
cout << endl;
return 0;
}