迭代快速排序方法

时间:2018-05-15 07:35:45

标签: c++ algorithm

原始问题的简短版本:我正在尝试转换此示例:迭代快速排序的http://programmertech.com/program/cpp/quick-sort-recursive-and-iterative-in-c-plus-plus使用向量而不是数组并开始简化一些事情。最初直接转换失败了,所以我逐行尝试了解它,以便更好地理解,但我的逻辑被卡住了。

编辑:从问题中删除了所有内容,提供了我正在尝试的最小(不太有效)的示例。这是我到目前为止所做的一切。我已经手工完成了这个工作,我越是触及它就越糟糕,现在陷入无限循环(最初没有正确排序)。

我的想法是: getMedian 因为我写过它应该交换枢轴值,以及左右值,以便它们被排序: left< = med< =对。当我们转到分区算法中的 while(右>左)循环时,它应该保持交换元素以将所有大于枢轴的元素放在右边的它和那些较少的左边。堆栈保持跟踪需要进行分区的Sub(向量)(在这种情况下)。但这似乎并没有奏效。我觉得好像错过了对这项工作非常重要的事情。

#include <iostream>
#include <vector>

class QuickSort {
public:
    QuickSort(std::vector<int> toBeSorted) : toBeSorted(toBeSorted) {}
    void sortVector();
    void print();
private:
    int partition(int left, int right);
    int getMedian(int left, int right);

    std::vector<int> toBeSorted;
};

// Iterative method using a stack
void QuickSort::sortVector() {
    int stack[toBeSorted.size()];
    int top = 0;
    stack[top++] = toBeSorted.size() - 1;
    stack[top++] = 0;

    int left, right, pivIndex;

    while (top > 0) {
        // Popping values for subarray
        left = stack[--top];
        right = stack[--top];
        pivIndex = partition(left, right);

        if (pivIndex + 1 < right) {
            stack[top++] = right;
            stack[top++] = pivIndex+1;
        }

        if (pivIndex - 1 > left) {
            stack[top++] = pivIndex-1;
            stack[top++] = left;
        }
    }
}

int QuickSort::partition(int left, int right) {
    int pivotValue = getMedian(left, right);

    if (right - left > 1) {
    while (right > left) {
        while (toBeSorted[left] < pivotValue) { left++; }
        while (toBeSorted[right] > pivotValue) { right--; }

        if (toBeSorted[right] < toBeSorted[left]) {
            std::swap(toBeSorted[right], toBeSorted[left]);
            left++;
            right--;
        }
    }
    } else {
        if (toBeSorted[right] < toBeSorted[left]) {
            std::swap(toBeSorted[right], toBeSorted[left]);
        }
    }
    return 0;
}

int QuickSort::getMedian(int left, int right) {
    int med = (right - left)/2;
    // if there are an even number of elements, instead of truncating
    // goto the rightmost value.
    if ((right - left)%2 != 0) {
        med = (right-left)/2 + 1;
    }

    // Organise the elements such that 
    // values at indexes: left <= med <= right.
    if (toBeSorted[med] < toBeSorted[left]) {
        std::swap(toBeSorted[left], toBeSorted[med]);
    }
    if (toBeSorted[right] < toBeSorted[left]) {
        std::swap(toBeSorted[left], toBeSorted[right]);
    }
    if (toBeSorted[right] < toBeSorted[med]) {
        std::swap(toBeSorted[right], toBeSorted[med]);
    }

    return toBeSorted[med];
}

void QuickSort::print() {
    for (int i = 0; i != toBeSorted.size(); i++) {
        std::cout << toBeSorted[i] << ",";
    }
    std::cout << std::endl;
}

int main() {
    std::vector<int> values = {5, 8, 7, 1, 2, 5, 3};
    QuickSort *sorter = new QuickSort(values);
    sorter->sortVector();
    sorter->print();
    return 0;
}

2 个答案:

答案 0 :(得分:1)

partition方法中,您不应该在每次迭代中swap(data[low], data[high])。你错了就是这个部分。你可以这样做:

void partition(int left, int right) {
  // listOfNums is a vector
  int middle = getMidPiv(left, right);
  int low = left;
  int high = right-1;

  while (low < high) {
    while (listOfNums[low] < middle) {
      lower++;
    }

    while (listOfNums[high] > middle) {
      high--;
    }

    if (low < high) {
       swap(data[low], data[high]);
       low++;
       high--;
    }
  }

  // swap(data[low], data[high]); it is incorrect
  return low;
}

答案 1 :(得分:0)

在第一个内部while循环中,使用 low ++ 而不是 lower ++ ,并将函数的返回类型更改为 int