1. 另一种快排的方式,注意枢轴元素的值是拿出来比较的,最后一刻才会确定枢轴元素所在的位置,值和位置需要注意区分
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void SwapInt(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
void Shuffle(int *array, int length) {
srand(time(NULL));
for (int i = length - 1; i > 0; --i) {
int random_number = rand() % i;
SwapInt(array + i, array + random_number);
}
}
// 不用指针的快排,不过是中间枢轴法
int PartitionNormal(int low, int high, int array[]){
int pivot = array[(low + high)/2];
int i = low;
int j = high;
while(i<j){
if(array[i] < pivot){
i++;
}
if(array[j] > pivot){
j--;
}
SwapInt(array+i, array+j);
}
return i;
}
void QuickSortNormal(int low, int high, int array[]){
if(low > high)
return;
int partition = PartitionNormal(low, high, array);
QuickSortNormal(low, partition-1,array);
QuickSortNormal(partition+1, high, array);
}
#define PLAYER_COUNT 20
int main() {
int *players = malloc(sizeof(int) * PLAYER_COUNT);
if (!players) {
return 1;
}
for (int i = 0; i < PLAYER_COUNT; ++i) {
players[i] = i;
}
Shuffle(players, PLAYER_COUNT);
printf("排序前:");
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d, ", players[i]);
}
QuickSortNormal(0, 19, players);
printf("\n排序后:");
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d, ", players[i]);
}
return 0;
}
对了,shuffle 那边有些变化,原先传进去的参数是 int array[],现在变成了 int *array,其实两者是一样的:
2. 指针版本的快排,把数组思想放弃,数组思想转变为一个内存指针的思想,数组的元素的下标和取值就是指针变量的各种运算,不再是对数组元素进行排序,而是对一个内存块进行排序
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void SwapInt(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
void Shuffle(int array[], int length) {
// 创建随机种子
srand(time(NULL));
for (int i = length-1; i > 0; --i) {
int random_number = rand() % i;
SwapInt(array+i, array+random_number);
}
}
int *PartitionPointer(int *low, int *high){
int pivot = *(low + (high-low)/2);
int* i = low;
int* j = high;
while(i < j){
if(*i < pivot){
i++;
}
if(*j > pivot){
j--;
}
SwapInt(i, j);
}
return i;
}
void QuickSortPointer(int *low, int *high){
if(low > high)
return;
int *partition = PartitionPointer(low, high);
QuickSortPointer(low, partition-1);
QuickSortPointer(partition+1, high);
}
#define PLAYER_COUNT 20
int main() {
int *players = malloc(sizeof(int) * PLAYER_COUNT);
if (!players) {
return 1;
}
for (int i = 0; i < PLAYER_COUNT; ++i) {
players[i] = i;
}
Shuffle(players, PLAYER_COUNT);
printf("排序前:");
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d, ", players[i]);
}
QuickSortPointer(players, players+PLAYER_COUNT-1);
printf("\n排序后:");
for (int i = 0; i < PLAYER_COUNT; ++i) {
printf("%d, ", players[i]);
}
return 0;
}
最后附上老师的代码:
int *Partition(int *low, int *high) {
int pivot = *(low + (high - low) / 2);
int *p = low;
int *q = high;
while (1) {
while (*p < pivot) p++;
while (*q > pivot) q--;
if (p >= q) break;
SwapInt(p, q);
}
return q;
}
void QuickSort(int *low, int *high) {
if (low >= high) return;
int *partition = Partition(low, high);
QuickSort(low, partition - 1);
QuickSort(partition + 1, high);
}
提问:
1. 为什么 (low + high)/2 没有 low + (high-low)/2 好,为什么后者可以防止溢出?
想象一下,如果下标是 98 亿 和 99亿 ,对比计算一下。其实后者并不是绝对防止溢出,而是扩展性更好,把大数计算转变为了小数计算,前者太依赖计算机的精度。