前言
学过算法与数据结构的人都知道,几乎所有教程都会讲排序,然而实际编程中并不会真正的手写排序算法,慢慢的大家是否会产生疑问,是不是只要了解各种排序算法的特点就好,不必过分执着于代码,然而最近,我对此有了更深刻的认识。
各种排序算法,实际深层次代表了不同的编程思想,并且好的实现方式,还运用了一些有用的编程技巧,这才是实际学习过程中真正需要掌握的东西,比如二分、递归等等。
细细把玩之后,会产生一种看山是山 看山不是山 看山还是山的感觉。
首先,对于各种排序算法,网上有非常多的教程,在此我就不多说了,没有看过的同学可以看下【十大经典排序算法】
下面我主要讲下我对快速排序与递归排序的一些感悟。
快速排序
这里用了一种递归的实现方式,关键点都在注释里了。
void swap(int *x, int *y) {
int t = *x;
*x = *y;
*y = t;
}
void QuickSort(int *arr, int start, int end)
{
if (start >= end) { // 一半递归的退出条件可以放在最后写,好的退出条件可以简化代码,但是可能会多一次递归调用,个中细节,自己写下就知道。
return;
}
int left = start;
int right = end - 1;
int privot = arr[end]; // 此处选最后一个数作为分隔点,实际privot的选取有很多种方法,好的方案能产生一定优化作用。
while (left < right) { // 经典双指针循环
while (left < right && arr[left] < privot)
left++;
while (left < right && arr[right] >= privot)
right--;
swap(&arr[left], &arr[right]);
}
// 此处对循环跳出后做处理,处理一些边界情况,必要时可以在循环中加flag
if (arr[left] >= privot) { // 调整privot的位置,只要保证小于privot的在同一边,大于的在另一边即可
swap(&arr[left], &arr[end]);
} else {
left++; // 此处对应left 一直左移到right,且当前left小于privot,则令left指向end
}
QuickSort(arr, start, left-1); // 递归调用,一般写到这,递归头部的退出条件便水到渠成
QuickSort(arr, left + 1, end);
}
// 借用力扣 912 题做验证
// https://leetcode-cn.com/problems/sort-an-array/
int* sortArray(int* nums, int numsSize, int* returnSize){
*returnSize = numsSize;
int *relt = (int *)malloc(sizeof(int) * numsSize);
for (int i = 0; i < numsSize; i++) {
relt[i] = nums[i];
}
QuickSort(relt, 0, numsSize-1);
return relt;
}
归并排序
void Merge(int *arr, int start, int mid, int end)
{
int *tmpArr = (int *)malloc(sizeof(int) * (end - start + 1));
int ptr1 = start;
int ptr2 = mid + 1;
int ptr = 0;
while (ptr1 <= mid && ptr2 <= end){
if (arr[ptr1] > arr[ptr2]) {
tmpArr[ptr++] = arr[ptr2];
ptr2++;
} else if (arr[ptr1] <= arr[ptr2]) {
tmpArr[ptr++] = arr[ptr1];
ptr1++;
}
}
while (ptr1 <= mid) { // 处理上面循环的尾巴
tmpArr[ptr++] = arr[ptr1++];
}
while (ptr2 <= end) {
tmpArr[ptr++] = arr[ptr2++];
}
for (int i = start; i <= end; i++) {
arr[i] = tmpArr[i - start];
}
return;
}
void MergeSort(int *arr, int start, int end)
{
if (start >= end) {
return;
}
// 分
int mid = (start + end) / 2;
MergeSort(arr, start, mid);
MergeSort(arr, mid + 1, end);
// 如果解决一个问题,使用两个有序序列可以很快解决,那么,可以在此加入处理代码
// 合
Merge(arr, start, mid, end);
}
int* sortArray(int* nums, int numsSize, int* returnSize){
*returnSize = numsSize;
int *relt = (int *)malloc(sizeof(int) * numsSize);
for (int i = 0; i < numsSize; i++) {
relt[i] = nums[i];
}
MergeSort(relt, 0, numsSize-1);
return relt;
}