选择排序
选择排序是一种简单直观的排序算法,时间复杂度为,其中 n 是数组长度,不适合大数据集的排序,适合于元素较少且对性能要求不高的场景。
选择排序的基本思想是:每次从未排序部分选择最小的元素,将其放到已排序部分的末尾。这样经过多轮操作后,整个数组会被逐步排好序。
具体步骤如下:
- 初始化:将第一个元素作为已排序区,剩余部分作为未排序区。
- 遍历未排序区:从未排序区间找出最小的元素,记下其位置。
- 交换位置:将找到的最小元素与当前未排序区的第一个元素交换。
- 重复上述步骤:每次将已排序区的范围扩大一个元素,直到整个数组排序完成。
题目要求
实现一个选择排序算法,用于对整数数组进行升序排序。输入是一个包含若干整数的数组,输出是排序后的数组。要求在原数组上进行排序,不借助额外的数组空间(即就地排序)。
做题思路
- 初始化已排序区间和未排序区间:数组已排序区间最开始为空,所有元素都在未排序区间中。
- 逐步扩展已排序区间:遍历数组,从未排序区间中找出最小值的下标,将其与当前未排序区间的起始元素交换。
- 更新边界:每次将已排序区间的范围扩大一个元素。
过程解析
假设有一个数组 arr,长度为 n。使用变量 minIndex 记录当前未排序区间中最小值的下标。具体步骤如下:
- 外层循环控制已排序区间的结束位置 i(从 0 开始)。
- 每次将未排序区间的第一个元素设为最小值(minIndex = i)。
- 内层循环从 i + 1 到 n - 1,找到未排序区间的最小值的下标并更新到 minIndex。
- 找到最小值后,与当前未排序区间的第一个元素交换位置(如果 i 和 minIndex 不相同)。
运用到的知识点
- 数组:数组的定义和遍历
- 双层循环:外层循环控制排序轮数,内层循环查找未排序区间的最小值
- 条件判断和交换操作:根据下标交换两个元素的值
示例代码
C 实现
#include <stdio.h> // 引入标准输入输出库,用于printf等函数
// 定义选择排序函数,接收一个整型数组和数组的长度作为参数
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) { // 外层循环:逐步将元素放入已排序区,从第一个元素开始到倒数第二个元素
int minIndex = i; // 假设当前未排序区第一个元素为最小值,记录其下标
for (int j = i + 1; j < n; j++) { // 内层循环:从当前元素的下一个元素开始,遍历未排序区
if (arr[j] < arr[minIndex]) { // 如果找到比当前最小值还小的元素
minIndex = j; // 更新最小值下标为当前更小元素的下标
}
}
if (minIndex != i) { // 如果找到的最小值不是当前元素(即最小值下标发生了改变)
int temp = arr[i]; // 交换元素,将找到的最小值元素与当前元素位置互换
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
// 定义打印数组函数,接收一个整型数组和数组的长度作为参数
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) { // 遍历数组
printf("%d ", arr[i]); // 打印每个元素,元素之间用空格分隔
}
printf("\n"); // 打印完所有元素后换行
}
int main()
{
int arr[] = { 64, 25, 12, 22, 11 }; // 定义一个整型数组并初始化
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组的长度,即数组中元素的个数
selectionSort(arr, n); // 调用选择排序函数对数组进行排序
printf("排序后的数组: "); // 打印提示信息
printArray(arr, n); // 调用打印数组函数输出排序后的数组
return 0; // 程序正常结束,返回0
}
C++ 实现
#include <iostream> // 引入输入输出流库,用于输入输出操作
#include <vector> // 引入向量库,用于使用动态数组
using namespace std; // 使用标准命名空间,避免每次调用标准库时都需要加std::前缀
// 定义选择排序函数,接收一个整数向量的引用作为参数,避免复制整个数组
void selectionSort(vector<int>& arr) {
int n = arr.size(); // 获取数组的长度
for (int i = 0; i < n - 1; i++) { // 外层循环:从第0个元素遍历到倒数第二个元素
int minIndex = i; // 假设当前未排序区的第一个元素为最小值,并记录其下标
for (int j = i + 1; j < n; j++) { // 内层循环:从当前元素的下一个元素开始,遍历未排序区
if (arr[j] < arr[minIndex]) { // 如果找到比当前最小值还小的元素
minIndex = j; // 更新最小值下标为当前更小元素的下标
}
}
if (minIndex != i) { // 如果找到的最小值下标不是当前元素的下标(即最小值发生了移动)
swap(arr[i], arr[minIndex]); // 使用C++内置的swap函数交换两个元素的位置,将最小值放到已排序区的末尾
}
}
}
// 定义打印数组函数,接收一个整数向量的常量引用作为参数,避免修改原数组
void printArray(const vector<int>& arr) {
for (int i : arr) { // 使用范围for循环遍历数组中的每个元素
cout << i << " "; // 打印每个元素,元素之间用空格分隔
}
cout << endl; // 打印完所有元素后换行
}
int main()
{
vector<int> arr = {64, 25, 12, 22, 11}; // 定义一个整数向量并初始化
selectionSort(arr); // 调用选择排序函数对数组进行排序
cout << "排序后的数组: "; // 打印提示信息
printArray(arr); // 调用打印数组函数输出排序后的数组
return 0; // 程序正常结束,返回0
}