给定一个不少于50个关键字的无序数据集合,在不排序的情况下用分治算法的思路找出与你的学号最后2位相等的第K小的关键字,(比如你的学号是19...XXXX16,那么你要编程找出第1 6小的那个关键字)。
2100300805: 找出第5小的关键字
少兵老师讲解:
mid = partitim(a,left,right);
mid = k = 5;
if(k==mid) return a[mid];
else if(k<mid)
0=partitim(a,left,right);
else
0=partitim(a,mid+1,right);
//2100300805
#include <stdio.h>
#include <stdlib.h>
/*
* 采用快速排序的思想,每次选取一个枢轴元素,将小于枢轴的元素放在左边,大于枢轴的元素放在右边
* 如果枢轴元素的下标为k-1,则该元素即为第k小的元素
* 如果枢轴元素的下标小于k-1,则在右边继续查找第k小的元素
* 如果枢轴元素的下标大于k-1,则在左边继续查找第k小的元素
* 时间复杂度为O(n),最坏情况下为O(n^2)
*/
#define MAX_SIZE 50
/* 定义函数quickSelect,用于在不排序的情况下查找第k小的元素*/
int quickSelect(int arr[], int left, int right, int k);
/* 主函数main*/
int main() {
// 定义一个包含50个元素的无序数组
int arr[MAX_SIZE] = {8, 3, 2, 7, 4, 6, 5, 1, 10, 9, 12, 11, 15, 14, 13, 18, 16, 17, 20, 19,
23, 21, 22, 25, 24, 28, 27, 26, 29, 32, 30, 31, 35, 34, 33, 36, 39, 37,
38, 42, 43, 40, 41, 46, 44, 45, 48, 50, 47, 49};
int len = sizeof(arr) / sizeof(int);//计算数组的长度
int k = 5;//查找第5小的元素
int res = quickSelect(arr, 0, len - 1, k - 1); // 注意k从0开始计数,因此要减1
printf("第%d小的关键字是%d\n", k, res);
return 0;
}
/* 定义函数partition,用于对数组进行划分*/
int partition(int arr[], int left, int right) {
int pivot = arr[left]; // 选取左端点作为枢轴
while (left < right) {
while (left < right && arr[right] >= pivot) { // 从右往左找到第一个小于枢轴的元素
right--;
}
arr[left] = arr[right]; // 将该元素移动到左端点
while (left < right && arr[left] <= pivot) { // 从左往右找到第一个大于枢轴的元素
left++;
}
arr[right] = arr[left]; // 将该元素移动到右端点
}
arr[left] = pivot; // 把枢轴放到最终位置
return left; // 返回枢轴所在的位置
}
// 定义函数quickSelect,用于在不排序的情况下查找第k小的元素
int quickSelect(int arr[], int left, int right, int k) {
if (left == right) { // 边界条件:只有一个元素
return arr[left];
}
int pivotIndex = partition(arr, left, right); // 划分数组
if (k == pivotIndex) { // 找到第k小的元素
return arr[k];
} else if (k < pivotIndex) { // 在左半部分继续查找第k小的元素
return quickSelect(arr, left, pivotIndex - 1, k);
} else { // 在右半部分继续查找第k小的元素
return quickSelect(arr, pivotIndex + 1, right, k);
}
}
举例分析: