Bootstrap

C/C++每日一练:实现选择排序

选择排序

        选择排序是一种简单直观的排序算法,时间复杂度为O(n^{2}),其中 n 是数组长度,不适合大数据集的排序,适合于元素较少且对性能要求不高的场景。

        选择排序的基本思想是:每次从未排序部分选择最小的元素,将其放到已排序部分的末尾。这样经过多轮操作后,整个数组会被逐步排好序。

        具体步骤如下:

  1. 初始化:将第一个元素作为已排序区,剩余部分作为未排序区。
  2. 遍历未排序区:从未排序区间找出最小的元素,记下其位置。
  3. 交换位置:将找到的最小元素与当前未排序区的第一个元素交换。
  4. 重复上述步骤:每次将已排序区的范围扩大一个元素,直到整个数组排序完成。

题目要求

        实现一个选择排序算法,用于对整数数组进行升序排序。输入是一个包含若干整数的数组,输出是排序后的数组。要求在原数组上进行排序,不借助额外的数组空间(即就地排序)。

做题思路

  1. 初始化已排序区间和未排序区间:数组已排序区间最开始为空,所有元素都在未排序区间中。
  2. 逐步扩展已排序区间:遍历数组,从未排序区间中找出最小值的下标,将其与当前未排序区间的起始元素交换。
  3. 更新边界:每次将已排序区间的范围扩大一个元素。

过程解析

        假设有一个数组 arr,长度为 n。使用变量 minIndex 记录当前未排序区间中最小值的下标。具体步骤如下:

  1. 外层循环控制已排序区间的结束位置 i(从 0 开始)。
  2. 每次将未排序区间的第一个元素设为最小值(minIndex = i)。
  3. 内层循环从 i + 1 到 n - 1,找到未排序区间的最小值的下标并更新到 minIndex。
  4. 找到最小值后,与当前未排序区间的第一个元素交换位置(如果 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  
}

;