合并排序
合并排序的基本思想是:将待排序元素分为大小大致相同的两个子集,分别对两个子集合进行排序,最终将排序好的子集合合并为所要求的排好序的集合。
具体步骤可以通过下列的动图查看:(引用自https://blog.csdn.net/li528405176/article/details/86615003)
void merge_sort_recursive(int arr[], int reg[], int start, int end)//仅列举函数
{
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(arr, reg, start1, end1);
merge_sort_recursive(arr, reg, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
reg[k++] = arr[start1++];
while (start2 <= end2)
reg[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = reg[k];
}
void merge_sort(int arr[], const int len) {
int reg[len];
merge_sort_recursive(arr, reg, 0, len - 1);
}
合并排序的最坏和平均复杂度均为O(nlogn)
快速排序
快速排序是最常用的排序算法。其原理如下:
1.设定一个基准A(一般是以第一个元素为基准),把大于这个基准A的数放在这个基准后,小于这个基准A的数字放在这个基准前;
2.对大于和小于基准A的部分分别使用步骤1,设定新的基准,划分数组,直到数组中只有一个元素为止。
这样说起来有些抽象,我们利用一个例子具体说明排序过程:
我们现在有无序的数组{6,7,5,2,5,8},第一次循环我们以6为基准。
首先,设置两个变量i,j记录位置(位置从0—5),初始时i=1,j=5,如图:
现在从后往前找第一个小于6的数字,j现在指向8,大于6,j减小,指向5,此时5小于6,如图:
交换i和j指向的元素位置,7和5交换位置得到结果如下:
现在从前往后找第一个大于6的数字,显然到7之前没有比6大的数字,而从后往前找第一个小于6的数字时,找到了2,也就是此时i>j,如图:
按理说i在前半部分,j在后半部分,但此时i>j了,因此,我们已经确定了,在j处(我们要保证从小到大排列 ,i指向的此时大于6),之前的数字小于6,之后的数字大于6,我们将6置换到j处,得到:
这就是一次快速排序的结果,之后我们分别再对前半部分和后半部分使用快速排序,直到每个数组只有一个数字的时候,我们的快速排序就完成了。
代码如下:
void QuickSort(int a[],int start,int last)
{
int i=start;
int j=last;
int temp=a[i];
if(i<j)
{
while(true)
{
while(a[i]<x)
{
i++;
}
while(a[j]>x)
{
j--;
}
if(i>=j) break;
int m=a[i];
a[i]=a[j];
a[j]=m;
}
a[i]=a[j];
a[j]=temp;
QuickSort(a,start,j-1);
QuickSort(a,j+1,last);
}
}
快速排序的最坏时间复杂度:O(n^2),平均时间复杂度为O(nlogn);