建议先去看看我之前写的基础排序算法
补充一:快排中partition函数的三种实现形式
1.hoare法---与第2种方法类似
int Partition1(int*a,int left,int right) {int keyi = left;while (left < right) {while (left < right && a[right] >= a[keyi])right--;while (left < right && a[left] <= a[keyi])left++;swap(&a[left],&a[right]);}swap(&a[keyi],&a[left]);return left;
}
2.挖坑法---也是基础排序算法里写的
int Partition2(int* a, int left, int right) {int key = a[left];while (left < right) {while (left < right && a[right] >= key)right--;a[left] = a[right];while (left < right && a[left] <= key)left++;a[right]=a[left];}a[left] = key;return left;
}
3.双指针法
int Partition3(int* a, int left, int right) {int keyi = left;int pre = left, cur = left + 1;while (cur <= right) {if (a[cur] < a[keyi]) {pre++;swap(&a[pre],&a[cur]);}cur++;}swap(&a[pre], &a[keyi]);return pre;
}
举个例子帮助大家理解一下双指针法
补充二:快排的非递归写法(栈的实现可以参考我之前写的栈和队列的实现)
本质和树的先序遍历的非递归写法一样
void QuickSortNonR(int* a, int left, int right) {ST st;StackInit(&st);//存放区间StackPush(&st, right);StackPush(&st, left);while (!StackEmpty(&st)) {int left = StackTop(&st);StackPop(&st);int right = StackTop(&st);StackPop(&st);int mid = PartSort1(a, left, right);if (mid - 1 > left) {//保证区间合法StackPush(&st, mid - 1);StackPush(&st, left);}if (mid + 1 < right) {//保证区间合法StackPush(&st, right);StackPush(&st, mid+1);}}StackDestroy(&st);
}
补充三:快排的三路划分写法---解决有多个重复数字的情况
//三路划分
void QuickSort_T(int* a, int left, int right) {if (left >= right)//保证区间合法return;int L = left, R = right;int key = a[left];int cur = left + 1;while (cur <= right) {if (a[cur] < key) {swap(&a[cur], &a[L]);L++;cur++;}else if (a[cur] == key) {cur++;}else {swap(&a[R], &a[cur]);R--;}}QuickSort_T(a, left, L - 1);QuickSort_T(a, R + 1, right);
}
举个例子
补充4:计数排序
void CountSort(int* a, int n) {int min = a[0], max = a[0];for (int i = 1; i < n; i++) {if (a[i] < min)min = a[i];if (a[i] > max)max = a[i];}int range = max - min + 1;int* count_a = (int*)malloc(sizeof(int) * range);memset(count_a, 0, sizeof(int) * range);for (int i = 0; i < n; i++) {count_a[a[i] - min]++;}for (int i = 0,k = 0; i < range; i++) {while(count_a[i]--) {a[k++] = i + min;}}
}
补充五:归并排序的小优化(递归)
void _MergeSort(int* a, int left, int right, int* tmp) {if (left >= right)return;//小区间优化if (right - left + 1 < 10) {InsertSort(a + left, right - left + 1);return;}int mid = left + (right - left) / 2;_MergeSort(a, left, mid, tmp);_MergeSort(a, mid+1,right, tmp);//这里只能分成[left,mid][mid+1,right](因为mid=(left+right)/2)//如果分成[left,mid-1][mid,right]//当left和right相差为1时,mid=left//那么dfs(left,right)//=>dfs(left,mid-1) dfs(mid,right)//<=>dfs(left,left-1) dfs(left,right)//<=>return dfs(left,mid-1) dfs(mid,right)//很显然,死递归了,问题就是在于dfs(left,right)一直在不停的重复递归int L1 = left, R1 = mid;int L2 = mid + 1, R2 = right;int k = 0;while (L1 <= R1 && L2 <= R2) {if (a[L1] < a[L2]) {tmp[k++] = a[L1++];}else{tmp[k++] = a[L2++];}}while (L1 <= R1)tmp[k++] = a[L1++];while (L2 <= R2)tmp[k++] = a[L2++];memcpy(a + left, tmp, sizeof(int) * k);
}
//归并
void MergeSort(int* a, int n) {int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(a, 0, n - 1, tmp);free(tmp);
}