#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_NUM 100
#define NUMS_LEN 20
/**
* 打印数组
* @param nums 数组指针
* @param len 数组长度
*/
void printNums(int *nums, int len) {
for (int i = 0; i < len; i++) {
printf("%d ", nums[i]);
}
printf("\n");
}
/**
* 生成随机数
* @return 返回一个数组指针
*/
int *randNums(int len, int maxNum) {
// 重置种子,不然每次生成的随机数是一样的
srand((unsigned) time(NULL));
int *nums = (int *) malloc(sizeof(int) * len);
for (int i = 0; i < len; i++) {
int randNum = rand() % maxNum;
nums[i] = randNum;
}
printf("生成随机数:");
printNums(nums, len);
return nums;
}
/**
* 分区
* @param nums 数组
* @param left 左指针
* @param right 右指针
* @param axis 轴指针
* @return 返回左指针向右移动的步数
*/
int partitionExchange(int *nums, int *left, int *right, int *axis) {
int leftStep = 0;// 记录左指针移动的步数
while (1) {
// 左指针和轴进行比较
while (1) {
if (*left <= *axis) {
// 如果左指针比轴要小,则左指针向又移动一格
if (left <= right) {
left += 1;
leftStep++;
} else {
// 已经顶到最右边了
break;
}
} else {
// 如果左指针并不比轴小,则停止移动左指针
break;
}
}
// 启动右指针,比较右指针和轴的大小
while (1) {
if (*right >= *axis) {
// 如果右指针比轴大,则右指针向左移
if (right >= left) {
right -= 1;
} else {
// 已经顶到最左边了
break;
}
} else {
// 如果右指针并不比轴大,则停止右指针
break;
}
}
// 如果左指针仍然在右指针的右边,则交换两个指针的位置的值
if (left < right) {
// 交换左指针和右指针的值
int temp = *left;
*left = *right;
*right = temp;
continue;
} else {
// 如果左指针和有指针重合,则无需再移动指针了, 将左指针的值和轴进行互换
int t = *axis;
*axis = *left;
*left = t;
break;
}
}
return leftStep;
}
/**
* 快速排序,Quicksort, 也被成为:partition-exchange sort
* @param nums 数组
* @param len 数组长度
*/
void partitionExchangeSort(int *nums, int len) {
if (len < 2) {
printf("数组元素小于2个,无需排序\n");
return;
}
// 每次选取数组的最后一个元素作为轴
int *axis = &nums[len - 1];
// 定义两个指针,分别指向排除轴元素之后,数组的最左和最右的元素
int *left = &nums[0];
int *right = &nums[len - 2];
int leftStep = partitionExchange(nums, left, right, axis);
// 左边数组为:0 到 leftStep-1
if (leftStep > 1) {
partitionExchangeSort(nums, leftStep);
}
// 右边数组为:leftStep+1 到 len-1
if (len - leftStep - 1 > 1) {
partitionExchangeSort(&nums[leftStep + 1], len - leftStep - 1);
}
}
/**
* 判断数组是否是排列好的升序
* @param nums 数组
* @param len 数组长度
* @return
*/
int isAsc(const int *nums, int len) {
for (int i = 0; i < len - 1; i++) {
if (nums[i] > nums[i + 1]) {
return 0;
}
}
return 1;
}
int main() {
int *nums;
int i = 0;// 去检验10000次
while (i++ < 10000) {
nums = randNums(NUMS_LEN, MAX_NUM);
partitionExchangeSort(nums, NUMS_LEN);
printf("排序完之后:");
printNums(nums, NUMS_LEN);
if (isAsc(nums, NUMS_LEN)) {
printf("第 %d 次测试成功\n", i);
} else {
printf("第 %d 次测试失败\n", i);
break;
}
printf("====================\n\n");
}
free(nums);
return 0;
}
运行:
gcc main.c
./a.out