如何使用first,middle和last元素的中位数正确分区?

时间:2018-04-11 01:02:37

标签: c++

我的multiway_merge功能不正确但不确定原因。似乎逻辑上是正确的,但如果排序是正确的,那么它必须是合并。我应该创建每个已排序向量的第一个元素的最小堆,然后以正确的排序顺序将它们添加到output_list,并继续这样做,直到所有数字都已添加到output_list。

int partition(vector<int>& list, int first, int last) {
    // The pivot should be the median of the
    // first, middle, and last elements.
    int middle = first + (last - first) / 2;

    if (list[first] > list[middle])
        swap(list[first], list[middle]);

    if (list[first] > list[last])       
        swap(list[first], list[last]);  

    if (list[middle] > list[last])
        swap(list[middle], list[last]);

    swap(list[middle], list[first]);            

    int pivot = list[first];
    int i = first - 1;
    int j = last + 1;

    while(true) {
        do {
            i++;
        } while(list[i] < pivot);

        do {
            j--;
        } while(list[j] > pivot);

        if(i >= j)                                  
            return j;

        swap(list[i], list[j]);
    }
}

void quicksort(vector<int>& list, int first, int last) {
    if(first < last) {
        int pivotLocation = partition(list, first, last);
        quicksort(list, first, pivotLocation);
        quicksort(list, pivotLocation + 1, last);
    }
}

void multiway_merge(vector<vector<int> >& input_lists, 
                    vector<int>& output_list) {

    int numLists = (int) (input_lists.size());
    int numElements = (int) (input_lists[0].size());
    priority_queue<int, vector<int>, greater<int> > minHeap;

    for(int i = 0; i < numLists; i++) {
        for(int j = 0; j < numElements; j++) {
            minHeap.push(input_lists[i][j]);

            if (minHeap.size() > numLists) {
                output_list.push_back(minHeap.top());
                minHeap.pop();
            }
        }
    }

    while (minHeap.size()) {
        output_list.push_back(minHeap.top());
        minHeap.pop();
    }
}

int main(int argc, char** argv) {
    int n, m;
    cin >> n >> m;

    vector<vector<int> > input_lists(n, vector<int>(m));

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> input_lists[i][j];
        }
    }

    // Quicksort k sublists
    for (int i = 0; i < input_lists.size(); ++i)
        quicksort(input_lists[i], 0, m-1);

    // Merge n input sublists into one sorted list
    vector<int> output_list;
    multiway_merge(input_lists, output_list);

    for(int i = 0; i < output_list.size(); ++i)
        cout << output_list[i] << " ";

    cout << endl;
}

1 个答案:

答案 0 :(得分:1)

我的partition函数无法找到任何逻辑错误,也许您的问题来源与您从sort函数调用此函数的方式相同而且您没有共享与我们一起运作所以我不得不猜测。

无论如何,使用partition函数的实现,快速排序算法将是这样的:

#include <iostream>
#include <vector>
#include <algorithm> 


int partition(std::vector<int> &vec, int low, int high)
{
    int middle = low + (high - low) / 2;

    if((vec.at(middle) >= vec.at(low) && vec.at(middle) <= vec.at(high))
        || (vec.at(middle) <= vec.at(low) && vec.at(middle) >= vec.at(high)))
        std::swap(vec.at(high), vec.at(middle));

    if((vec.at(high) >= vec.at(low) && vec.at(high) <= vec.at(middle))
        || (vec.at(high) <= vec.at(low) && vec.at(high) >= vec.at(middle)))
        std::swap(vec.at(low), vec.at(high));


    int pivot = vec.at(low);
    int i = low - 1, j = high + 1;

    while(true)
    {
        do
        {
            i++;
        } while(vec.at(i) < pivot);

        do
        {
            j--;
        } while(vec.at(j) > pivot);

        if(i >= j)
            return j;

        std::swap(vec.at(i), vec.at(j));
    }
}

void quickSort(std::vector<int> &vec, int low, int high)
{
    if(low < high)
    {
        int pi = partition(vec, low, high);
        quickSort(vec, low, pi);
        quickSort(vec, pi + 1, high);
    }
}

int main()
{
    std::vector<int> input = {10, 7, 15, 9, 1, 33};
    quickSort(input, 0, input.size() - 1);

    for(auto iter = input.begin(); iter != input.end(); ++iter)
        std::cout << *iter << " ";
    std::cout << "\n";

    system("pause");
    return 0;
}

编辑:您的快速排序不是问题的根源,您在合并排序的向量时遇到问题,因此问题的根源在于multiway_merge函数的逻辑。

您使用priority_queue来实现此合并,这是一种有效的方法,但我想您很想知道priority_queue实际上是如何运作的。

您可以将所需的元素排队,但传出元素的顺序取决于您设置优先级的方式。在priority_queue获取战利品。

确定优先级的比较条件也是正确的,我的意思是使用greater<int>。因此,代码中唯一的问题是您根本不需要它的一个额外条件。我的意思是这些代码行:

if(minHeap.size() > numLists)
{
    output_list.push_back(minHeap.top());
    minHeap.pop();
}

删除此条件,您的multiway_merge将正常运行。该函数的最终实现将是:

void multiway_merge(vector<vector<int> >& input_lists,
    vector<int>& output_list)
{

    unsigned int numLists = (int)(input_lists.size());
    int numElements = (int)(input_lists[0].size());
    priority_queue<int, vector<int>, greater<int> > minHeap;

    for(int i = 0; i < numLists; i++)
    {
        for(int j = 0; j < numElements; j++)
        {
            minHeap.push(input_lists[i][j]);
        }
    }

    while(minHeap.size())
    {
        output_list.push_back(minHeap.top());
        minHeap.pop();
    }
}