快速排序(QuickSort)

快速排序

#include <iostream>
#include <algorithm>

using namespace std;

//快速排序
void QuickSort1(int* arr, int low, int high) {
    if (low < high) {
        int pivot = arr[low];
        int start = low, end = high;
        while (low < high) {
            while (low < high && pivot <= arr[high])
                high--;
            arr[low] = arr[high];
            while (low < high && pivot >= arr[low])
                low++;
            arr[high] = arr[low];
        }
        arr[low] = pivot;
        int pivotpos = low;
        QuickSort1(arr, start, pivotpos - 1);
        QuickSort1(arr, pivotpos + 1, end);
    }
}

void QuickSort2(int* arr, int low, int high) {
    if (low >= high) return;
    int front = low, rear = high;
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] >= pivot)
            high--;
        while (low < high && arr[low] <= pivot)
            low++;
        if (low < high)
            swap(arr[low], arr[high]);
    }
    swap(arr[front], arr[low]);
    QuickSort2(arr, front, low - 1);
    QuickSort2(arr, low + 1, rear);
}

//(***最优***)
void QuickSort3(int arr[], int low, int high) {
    if (low >= high) return;

    int i = low - 1, j = high + 1; // 从界外开始
    int x = arr[(low + high) >> 1];  // 基准值为中间位置的数值

    while (i < j) {
        do i++; while (arr[i] < x); // i哨兵向右走,找到第一个大于等于基准值的数
        do j--; while (arr[j] > x); // j哨兵向左走,找到第一个小于等于基准值的数

        if (i < j) swap(arr[i], arr[j]); // 如果还没有碰面,就对调一下
    }

    // 递归排序左半部分和右半部分
    QuickSort3(arr, low, j);
    QuickSort3(arr, j + 1, high);
}

int main() {
    int n;
    cin >> n;  // 输入数组大小
    int* arr = new int[n];  // 创建数组
    for (int i = 0; i < n; i++) {
        cin >> arr[i];  // 输入数组元素
    }

    //QuickSort1(arr, 0, n - 1);
    //QuickSort2(arr, 0, n - 1);
    QuickSort3(arr, 0, n - 1);

    // 输出排序后的数组
    for (int i = 0; i < n; i++) {
        cout << arr[i];
        if (i < n - 1) cout << " ";  // 除了最后一个元素外,后面有空格
    }
    return 0;
}

上述代码实现了三种不同的快速排序算法(QuickSort1QuickSort2QuickSort3),并且通过 main 函数对它们进行了测试。以下是对每种实现的详细分析以及改进建议:


QuickSort1 分析

实现特点:

  • 选择 arr[low] 作为基准(pivot)。
  • 使用双指针(lowhigh)进行分区。
  • 分区过程中直接覆盖元素,最后将基准值放回正确位置。

改进建议:

  • 基准选择:选择 arr[low] 作为基准可能导致最坏情况(例如数组已经有序时)。可以通过随机选择基准来优化。
  • 代码可读性:添加注释,解释分区逻辑。

改进后的代码:

void QuickSort1(int* arr, int low, int high) {
    if (low < high) {
        // 随机选择基准元素
        int randomIndex = low + rand() % (high - low + 1);
        swap(arr[low], arr[randomIndex]);
        int pivot = arr[low];

        int start = low, end = high;
        while (low < high) {
            while (low < high && pivot <= arr[high])
                high--;
            arr[low] = arr[high];
            while (low < high && pivot >= arr[low])
                low++;
            arr[high] = arr[low];
        }
        arr[low] = pivot;
        int pivotpos = low;

        // 递归排序左半部分和右半部分
        QuickSort1(arr, start, pivotpos - 1);
        QuickSort1(arr, pivotpos + 1, end);
    }
}

QuickSort2 分析

实现特点:

  • 选择 arr[low] 作为基准。
  • 使用双指针(lowhigh)进行分区。
  • 在分区过程中,通过 swap 交换元素,而不是直接覆盖。

改进建议:

  • 基准选择:同样可以通过随机选择基准来优化。
  • 代码可读性:添加注释,解释分区逻辑。

改进后的代码:

void QuickSort2(int* arr, int low, int high) {
    if (low >= high) return;

    // 随机选择基准元素
    int randomIndex = low + rand() % (high - low + 1);
    swap(arr[low], arr[randomIndex]);
    int pivot = arr[low];

    int front = low, rear = high;
    while (low < high) {
        while (low < high && arr[high] >= pivot)
            high--;
        while (low < high && arr[low] <= pivot)
            low++;
        if (low < high)
            swap(arr[low], arr[high]);
    }
    swap(arr[front], arr[low]);

    // 递归排序左半部分和右半部分
    QuickSort2(arr, front, low - 1);
    QuickSort2(arr, low + 1, rear);
}

QuickSort3 分析

实现特点:

  • 选择中间元素 arr[(low + high) >> 1] 作为基准。
  • 使用双指针(ij)从数组两端向中间扫描。
  • 通过 swap 交换元素,直到指针相遇。

优点:

  • 基准选择较为合理,避免了最坏情况。
  • 代码逻辑清晰,易于理解。

改进建议:

  • 代码可读性:添加注释,解释指针移动和交换的逻辑。

改进后的代码:

void QuickSort3(int arr[], int low, int high) {
    if (low >= high) return;

    int i = low - 1, j = high + 1; // 从界外开始
    int x = arr[(low + high) >> 1];  // 基准值为中间位置的数值

    while (i < j) {
        do i++; while (arr[i] < x); // i哨兵向右走,找到第一个大于等于基准值的数
        do j--; while (arr[j] > x); // j哨兵向左走,找到第一个小于等于基准值的数

        if (i < j) swap(arr[i], arr[j]); // 如果还没有碰面,就对调一下
    }

    // 递归排序左半部分和右半部分
    QuickSort3(arr, low, j);
    QuickSort3(arr, j + 1, high);
}

main 函数分析

实现特点:

  • 测试了三种快速排序算法。
  • 输出排序前后的数组。

改进建议:

  • 释放动态分配的内存:如果使用动态数组,记得释放内存。
  • 代码可读性:添加注释,解释测试逻辑。

改进后的代码:

int main() {
    int arr[9] = {6, 4, 7, 9, 1, 6, 2, 98, 1};
    int len = sizeof(arr) / sizeof(int);

    cout << "排序前的: ";
    for (int i = 0; i < len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;

    cout << "长度:" << len << endl;

    // 选择一种快速排序算法进行测试
    // QuickSort1(arr, 0, len - 1);
    // QuickSort2(arr, 0, len - 1);
    QuickSort3(arr, 0, len - 1);

    cout << "排序后的: ";
    for (int i = 0; i < len; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;

    return 0;
}

总结

  • QuickSort1QuickSort2:可以通过随机选择基准来优化性能。
  • QuickSort3:实现较为合理,基准选择避免了最坏情况。
  • 代码风格:添加注释,提高代码可读性。
  • 测试:通过 main 函数测试了三种算法的正确性。
posted @ 2025-02-15 17:47  goalhome  阅读(44)  评论(0)    收藏  举报