【问题标题】:Quick Sort in C++ not working when middle element chosen as pivot当中间元素选择为枢轴时,在C ++中快速排序
【发布时间】:2017-07-11 10:13:59
【问题描述】:

我已经尝试在 c++ 中实现快速排序。我面临一个问题。如果我任意选择枢轴作为第一个或最后一个元素,程序运行良好,但如果我选择中间元素作为枢轴( (beg + end)/2 ),则输出并不完全正确。大多数元素是按排序顺序排列的,只有一些在随机的、不正确的位置。以下是我的代码:

#include <iostream>
#include <cstdlib>
#include <chrono>
#include <fstream>

using namespace std;
using namespace std::chrono;

void quickSort(int[], int, int);
void print(int);

void print(int n) //prints 50 random numbers in a file
{
    ofstream of("List.txt");
    int i;
    for (i = 0; i < n; i++)
    {
        int x = rand() % 50 + 1;
        of << x << endl;
    }
    of.close();
}

int sortf() //calls the quicksort function and sends it array of elements which
{           //were previously stored in the file and outputs sorted values to another file
    int arr[50];
    int n = 50;
    ifstream f("List.txt");
    int counter = 0;
    int i;
    while (!f.eof() && counter < 50)
    {
        f >> arr[counter];
        counter++;
    }
    quickSort(arr, 0, 49);
    ofstream of("ListOut.txt");
    for (i = 0; i < n; i++)
    {
        of << arr[i] << endl;
    }
}

void quickSort(int arr[], int start, int end) //applies quicksort algorithm
{
    if (start < end)
    {
        int a = start;
        int b = end;
        int p = arr[(a + b) / 2];
        int x = (a + b) / 2;
        int temp;
        while (a < b)
        {
            while (arr[b] > p)
            {
                b--;
            }
            while (arr[a] <= p && a <= b)
            {
                a++;
            }
            if (a < b)
            {
                temp = arr[b]; //swapping left and right position elements
                arr[b] = arr[a];
                arr[a] = temp;
            }
        }

        temp = arr[b]; //bringing pivot in the middle, so that
        arr[b] = arr[x]; //elements smaller than pivot are to the left
        arr[x] = temp; //and elements greater than pivot are to the right
        quickSort(arr, start, b - 1);
        quickSort(arr, b + 1, end);
    }
}

int main()
{
    print(50); //printing 50 numbers in the file
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    sortf();
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<nanoseconds>(t2 - t1).count();
    cout << "\nTime taken:\n" << duration; //outputs time taken for input, sorting and output.
}

执行后的输出文件包含以下元素列表:

3 16 7 9 25 12 10 12 13 14 24 18 13 16 18 18 21 19 20 20 22 22 23 23 24 27 27 28 30 28 30 30 31 33 34 35 36 41 36 37 37 37 38 41 43 43
44 44 49 50

请帮助我更正我的代码,因为我在这个小问题上浪费了很多时间。

【问题讨论】:

  • 1.选择一个分区不正确的特定小型数组(可能是 5 个元素)。 2.逐行运行,看看哪里出错了。 3. ??? 4. 利润。
  • 在自称浪费时间的那几个小时里,您是否有可能通过 调试器 运行此程序,单步执行以更好地理解 为什么 事情会中断使用中间元素枢轴选择?
  • 嗯,这就是问题所在,我是 C++ 新手,不知道如何使用调试器。任何更正将不胜感激。我需要尽快的代码,因为我必须实现多种排序算法并分析它们,以便明天提交朋友的项目,除快速排序外,其他一切都在工作。
  • 在不知道如何使用调试器的情况下尝试学习 C++ 基本上是盲目的编程。您需要弄清楚如何“尽快”使用调试器,否则您将永远无法到达任何地方。调试器的基础知识并不难掌握,您可能需要知道如何使用四个按钮。其余的你可以根据需要学习。
  • 我会再次检查该行。最后说服我懒惰的自己改用 Netbeans 并使用它的调试器。看起来没那么难!

标签: c++ algorithm sorting c++11 quicksort


【解决方案1】:

我自己使用调试器找到了解决方案。请参阅大写注释以了解为更正代码所做的更改。以下是 10000 个输入值的快速排序实现的工作代码:

#include <iostream>
#include <cstdlib>
#include <chrono>
#include <fstream>

using namespace std;
using namespace std::chrono;

void quickSort(int[], int, int);
void print(int);

void print(int n) //prints 50 random numbers in a file
{
    ofstream of("List.txt");
    int i;
    for (i = 0; i < n; i++)
    {
        int x = rand() % 10000 + 1;
        of << x << endl;
    }
    of.close();
}

void sortf(int x) //calls the quicksort function and sends it array of elements which
{           //were previously stored in the file and outputs sorted values to another file
    int arr[x];
    int n = x;
    ifstream f("List.txt");
    int counter = 0;
    int i;
    while (!f.eof() && counter < x)
    {
        f >> arr[counter];
        counter++;
    }
    quickSort(arr, 0, x-1);
    ofstream of("ListOut.txt");
    for (i = 0; i < n; i++)
    {
        of << arr[i] << endl;
    }
}

void quickSort(int arr[], int start, int end) //applies quicksort algorithm
{
    if (start < end)
    {
        int a = start;
        int b = end;
        int p = arr[(a + b) / 2];
        int x = (a + b) / 2;
        int temp;
        while (a < b)
        {
            while (arr[b] > p)
            {
                b--;
            }
            while (arr[a] <= p && a <= b)
            {
                a++;
            }
            if (a < b)
            {
                temp = arr[b]; //swapping left and right position elements
                arr[b] = arr[a];
                arr[a] = temp;
            }
        }
        arr[b] = p; //CHANGED THIS ***************
        quickSort(arr, start, b - 1);
        quickSort(arr, b + 1, end);
    }
}

int main()
{
    print(10000); //printing 50 numbers in the file
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    sortf(10000);
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<nanoseconds>(t2 - t1).count();
    cout << "\nTime taken:\n" << duration; //outputs time taken for input, sorting and output.
}

感谢您的有用建议。非常感谢你们坚持使用调试器。学到了一些新的并且非常有用的东西,现在我的代码可以正常工作,输入 10000 个值。干杯!

【讨论】:

  • int arr[x] -- 请注意,这不是有效的 C++。 C++ 要求数组使用编译时常量来指定条目数,而不是变量。您的程序将无法使用 Visual Studio 进行编译,也将无法使用 g++ 使用 -pedantic - Wall 编译选项进行编译。如果您想使用标准 C++,请将其更改为 std::vector&lt;int&gt; arr(x); 并将 arr.data() 传递给仍需要 int * 的函数。
  • 这只是一个试验。我将在代码的最终版本中使用向量。
  • 那么试验并没有足够的说服力来确定是否存在任何偏离一的边界条件错误。您应该更改为std::vector 以确保不会发生静默错误。你超出了数组的范围,行为是未定义的。您使用矢量越界,然后您有 at() 来帮助确定这一点。
  • 另外,您的 sortf 函数在应该返回 int 时没有返回值。这是未定义的行为。
  • 是的,我错过了,感谢您指出那个。妈的,我现在需要睡觉了。矢量版运行良好,我的朋友很高兴。
猜你喜欢
  • 2019-11-23
  • 2010-09-14
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 2011-08-31
  • 2015-05-04
相关资源
最近更新 更多