C ++中的无限递归Quicksort

时间:2014-01-09 00:36:45

标签: c++ sorting quicksort

我正在尝试编写quicksort的一个版本,但这只是不起作用。当我运行它时,它首先给出堆栈溢出错误,然后继续发送访问写入违规错误。手动完成并使用调试器显示它只是一个无限循环。此外,错误似乎源于swapmove函数本身(不是我调用swap),但我根本没有改变它们。

int list[10];
int i;
int length = 10;

void quicksort(int thelist[], int first, int last)
{
    int lower = first + 1;
    int upper = last;
    swap(thelist[first], thelist[(first + last) / 2]);
    int pivot = thelist[first];
    while (lower <= upper)
    {
        while (thelist[lower] < pivot)
        {
            lower++;
        }
        while (pivot < thelist[upper])
        {
            upper--;
        }
        if (lower < upper)
        {
            swap(thelist[lower+1], thelist[upper-1]);
            lower++;
            upper--;
        }
        else
        {
            lower++;
        }
    }
    swap(thelist[upper], thelist[upper-1]);
    upper = upper - 1;
    if (first < upper - 1)
    {
        quicksort(thelist, first, upper - 1);
    }
    if (upper + 1 < last)
    {
        quicksort(thelist, upper + 1, last);
    }
    return;
}

void arrayout()
{
    cout << "Current array:";
    cout << endl;
    cout << endl;
    int h;
    for (h = 0; h < 10; h++)
    {
        cout << list[h];
        cout << endl;
    }
}

void max_end(int thelist[], int n)
{
    int max;
    if(n < 2)
    {
        return;
    }
    for(i = 1, max = 0; i < n; i++)
    {
        if(thelist[max] < thelist[i])
        {
            max = i;
        }
    }
    swap(thelist[n], thelist[max]);
    quicksort(thelist, 0, n-1);
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << "Hello! Welcome to the quick sort." << endl << "First, I will generate a random series of 10 numbers from 1-100." << endl << "Generating..." << endl;
    int randnum;
    srand(time(NULL));
    randnum = rand() % 2;
    for (i = 0; i < 10; i++)
    {
        randnum = rand() % 100 + 1;
        rand();
        list[i] = randnum;
        randnum = rand() % 100 + 1;
        rand();
    }
    randnum = rand() % 100 + 1;
    cout << "Generated!" << endl << endl;
    arrayout();
    cout << "Sorting..." << endl << endl;
    clock_t start = clock();
    max_end(list, length - 1);
    clock_t end = clock();
    arrayout();
    double diff = end - start;
    double diffmilli = 1000 * diff / CLOCKS_PER_SEC;
    cout << "Sorted!" << endl << "Time elapsed- " << diffmilli << " milliseconds." << endl << endl << "Just input something random once you're done."; >> endl;
    string nothing;
    cin >> nothing;
    return 0;
}

(这是交换/移动功能,以防万一有错误)

// TEMPLATE FUNCTION _Move
template<class _Ty> inline
    typename tr1::_Remove_reference<_Ty>::_Type&&
        _Move(_Ty&& _Arg)
    {   // forward _Arg as movable
    return ((typename tr1::_Remove_reference<_Ty>::_Type&&)_Arg);
    }

        // TEMPLATE FUNCTION swap (from <algorithm>)
template<class _Ty> inline
    void swap(_Ty& _Left, _Ty& _Right)
    {   // exchange values stored at _Left and _Right
    _Ty _Tmp = _Move(_Left);
    _Left = _Move(_Right);
    _Right = _Move(_Tmp);
    }

2 个答案:

答案 0 :(得分:0)

你的程序存在多个问题,我已经给出了以下列表

  1. 在while#1低于&lt; = upper的情况下,应低于&lt; upper,因为当索引相同时我们不进行任何交换(无限循环(?)的原因)
  2. 在while循环#2&amp;&amp; #3它们应该是“低于&lt; upper&amp;&amp; thelist [lower]&lt; pivot”和“lower&lt; upper&amp;&amp; pivot&lt; thelist [upper]”
  3. 在行“swap(thelist [upper],thelist [upper-1]);”你试图将你的枢轴交换回它的位置(不是你在[list]中的枢轴而不是在[list]列表中,用thelist [first]替换list [upper])
  4. 在交换枢轴之前需要找到枢轴适合的位置,因此添加“if(pivot&gt; thelist [upper])upper ++;”在交换枢轴之前
  5. 你可以删除while循环#1中最后一个if语句的else部分,因为它没有添加值
  6. 我认为应该让你的程序运作!我没有Microsoft C ++来测试你是否在测试中自己:(

答案 1 :(得分:0)

正如已经在这里预先确定的那样,问题不是(显然)在swapmove函数中,而是在某些情况下,在递归quicksort函数中,另一个,在腐败的记忆quicksort功能。要检测索引何时超出范围,可以使用assert的包装函数,如下所示:

void safeSwap(int thelist[], const int first, const int last, const int lower, const int upper)
{
    assert(first <= lower);
    assert(first <= upper);
    assert(lower <= last);
    assert(upper <= last);

    swap(thelist[lower], thelist[upper]);
}

void safeQuicksort(int thelist[], const int first, const int last, const int lower, const int upper)
{
    assert(first <= lower);
    assert(first <= upper);
    assert(lower <= last);
    assert(upper <= last);

    quicksort(thelist, lower, upper);
}

编辑有效的quicksort版本:

void quicksort(int thelist[], const int first, const int last)
{
    //assert(first < last);
    if (last - first < 2)   //  avoid infinite recurrence 
    {
        if (thelist[first] > thelist[last])
            swap(thelist[first], thelist[last]);
        return;
    }

    int lower = first;
    int upper = last;
    //  choose the middle as pivot to avoid further swappings
    int pivot = thelist[(first + last) / 2];

    while (lower < upper)
    {
        while (thelist[lower] < pivot)
        {
            lower++;
        }
        while (pivot < thelist[upper])
        {
            upper--;
        }

        if (lower < upper)
        {
            swap(thelist[lower], thelist[upper]);
            lower++;
            upper--;
        }
    }

    if (first < upper)
    {
        quicksort(thelist, first, upper);
    }
    if (lower < last)
    {
        quicksort(thelist, lower, last);
    }
}

void max_end(int thelist[], int n)
{
    quicksort(thelist, 0, n);
}

我尽量保持你的风格(我不使用全局变量,没有大小参数的数组)和你的算法(我更喜欢迭代器方法更多:In-place version)。

你可以这样做来测试它是否真正排序:

int i;
for (i = 1; (i < 10) && (list[i] >= list[i-1]); i++);
assert(10 == i);

我为几个特殊情况和一个巨大的循环做了这件事(500个randoms:记得只调用srand一次;)!)。