简体   繁体   English

如何在C ++中实现快速排序算法

[英]how to implement quick sort algorithm in C++

here is the of quick sort algorithm from the MITOcw( Introduction To Algorithms ) lecture 这是MITOcw( Introduction to Algorithms )讲座中的快速排序算法

QUICKSORT(A,p,q)
if(p < q)
then r = PARTITION(A,p,q)
     QUICKSORT(A,p,r-1)
     QUICKSORT(A,r+1,q)

PARTITION(A,p,q)
x = A[p]
i=p
for j = p+1 to q
    if A[j] <= x
       then i = i+1
            swap A[i] with A[j]
swap A[p] with A[i]
return i

and here its C++ implementation on an integer array 这里是整数数组上的C ++实现

#include <iostream>

using namespace std;

void quickSort(int *,int,int);

int partition(int *, int,int);

int main()
{
    int A[10]={6,10,13,5,8,3,2,25,4,11};
    int p=0,q=10;

    cout<<"======Original======="<<endl;
    for(int f=0; f<10; f++)
        cout<<A[f]<<endl;

    quickSort(A,p,q);

    cout<<"======Sorted======="<<endl;
    for(int f=0; f<10; f++)
        cout<<A[f]<<endl;
}


void quickSort(int *A, int p,int q)
{
    int r;
    if(p<q)
    {
        r=partition(A, p,q);
        quickSort(A,p,(r-1)); //I think the problem is here this first quickSort call
                              // is reducing the value of r and hence value of q becomes
                              // less than p recursively. How can I separate both calls
                              // one for left and one for right sub array of the pivot. 
        quickSort(A,(r+1),q);
    }
}


int partition(int *A, int p,int q)
{
    int x= A[p];
    int i=p;
    int temp;
    int j;

    for(j=p+1; j<q; j++)
    {
        if(A[j]<=x)
        {
            i=i+1;
            temp= A[j];
            A[j]=A[i];
            A[i]=temp;
        }

    }

    temp= A[p];
    A[p]=A[i];
    A[i]=temp;

    return i;
}

code doesn't yield sorted array although the first two runs of quickSort function gives desired output. 尽管前两次运行的quickSort函数提供了所需的输出,但代码不会产生排序数组。 that is it place the first pivot element to its correct position 也就是说它将第一个枢轴元素放置到正确的位置

Your consideration is wrong. 你的考虑是错误的。 The value of r does not change, since it is given as value to the Quicksort function(not a reference). r的值不会改变,因为它是作为Quicksort函数(不是引用)的值给出的。 You handle the ranges with p , q such that p is the first index in the range and q the first index not in the range. 使用pq处理范围,使得p是范围中的第一个索引, q不在范围内的第一个索引。

Thus, your calls were wrong: 因此,你的电话错了:

r=partition(A, p,q);
quickSort(A,p,r); //range is from A[p] to A[r-1] 
quickSort(A,(r+1),q); //range is from A[r+1] to A[q-1]

Here is the complete example. 这是完整的例子。 I used std::swap to change elements and ans std::vector instead of an array. 我用std :: swap来改变元素和ans std :: vector而不是数组。

#include <iostream>
#include <vector>

using namespace std;

void quickSort(vector<int>&,int,int);

int partition(vector<int>&, int,int);

int main()
{
    vector<int> A = {6,10,13,5,8,3,2,25,4,11};
    int p=0;
    int q=10;

    cout<<"======Original======="<<endl;
    for(auto e: A)
        cout<< e <<" ";
    cout<< endl;    

    quickSort(A,p,q);

    cout<<"======Sorted======="<<endl;
    for(auto e: A)
        cout<< e <<" ";
    cout<< endl;   
}


void quickSort(vector<int>& A, int p,int q)
{
    int r;
    if(p<q)
    {
        r=partition(A, p,q);
        quickSort(A,p,r);  
        quickSort(A,r+1,q);
    }
}


int partition(vector<int>& A, int p,int q)
{
    int x= A[p];
    int i=p;
    int j;

    for(j=p+1; j<q; j++)
    {
        if(A[j]<=x)
        {
            i=i+1;
            swap(A[i],A[j]);
        }

    }

    swap(A[i],A[p]);
    return i;
}

Live example: ideone 实例: ideone

This is a template based solution. 这是一个基于模板的解决方案。 However, it works only for arrays of elements for now. 但是,它现在只适用于元素数组。 If anyone has an improvement to make it generic for both arrays and STL containers, please do so. 如果任何人都有一个改进,使其成为阵列和STL容器的通用,请执行此操作。

template<typename T, typename compare = std::less<T>>
void q_sort(T input[], int l_idx, int r_idx, compare comp = compare()) {

    if (l_idx >= r_idx)
        return;

    // The below is the partition block (can be made a sub function)

    int left = l_idx;
    int right = r_idx;
    {
        int pivot_idx = l_idx;
        T pivot = input[pivot_idx];

        while (left < right) {
            while (comp(input[left], pivot))
                left++;
            while (comp(pivot, input[right]))
                right--;
            swap(input[left], input[right]);
        }

        swap(pivot, input[left]);
    }

    q_sort(input, l_idx, left, comp);
    q_sort(input, left+1, r_idx, comp);

}

template<typename T, typename compare = std::less<T>>
void quick_sort(T array[], int N, compare comp = compare()) {
    // This is an improvisation on the merge sort algorithm
    // is in-place and works on the divide-and-conquer methodology
    // Choose a pivot and find its appropriate place, such that
    // All elements less than the pivot are on its left and all elements
    // greater are on its right. Once found, split the porlblem into subsets
    // of elements less than and greater than the pivot and recursively
    // follow the process.
    q_sort(array, 0, N-1, comp);

}

int main()
{

    int input[] = {11, 6, 3, 21, 9, 12};
    std::cout << "Before : ";
    for (int i=0; i < 6; i++)
        std::cout << input[i] << " ";
    std::cout << std::endl;

    quick_sort(input, 6);
    // or 
    //quick_sort(input, 6, std::greater<int>());

    std::cout << "After : ";
    for (int i=0; i < 6; i++)
        std::cout << input[i] << " ";
    std::cout << std::endl;

}

A much easier and clean implementation, also gives you number of minimum SWAPS in for QuickSort: 更简单,更干净的实现,还为QuickSort提供了最小SWAPS数量:

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

int partition(int[], int, int, int&);

int main()
{
    int array[] = {4, 2, 5};
    int size = sizeof(array)/sizeof(array[0]);

    /*
     first and last indices are passed
     idea is to move lower elements to the left of the list/pivot
     */

    int swaps = quickSort(array, 0, size-1);

    std::cout << "Minimum Swaps are: " << swaps << std::endl;

    for(int i = 0; i < size; i++)
    {
        std::cout << array[i] << " ";
    }
}

int quickSort(int array[], int start, int end)
{
    int swaps = 0;
    if(start < end)
    {
        int pIndex = partition(array, start, end, swaps);
        //after each call one number(the PIVOT) will be at its final position
        swaps += quickSort(array, start, pIndex-1);
        swaps += quickSort(array, pIndex+1, end);
    }
    return swaps;
}

int partition(int array[], int start, int end, int& swaps)
{
    int pivot = array[end];
    int pIndex = start;

    for(int i = start; i < end; i++)
    {
        if(array[i] <= pivot)
        {

            if(pIndex != i)
            {
                std::swap(array[i], array[pIndex]);
                swaps++;
            }
            pIndex++;
        }
    }
    if(pIndex != end)
    {
        std::swap(array[pIndex], array[end]);
        swaps++;
    }
    return pIndex;
}

Since I see various answers, you could try this: 由于我看到了各种答案,你可以试试这个:

#include <iostream>

void quickSort(int a[], int first, int last);
int pivot(int a[], int first, int last);
void swap(int& a, int& b);
void swapNoTemp(int& a, int& b);
void print(int array[], const int& N);

using namespace std;

int main()
{
    int test[] = { 7, -13, 1, 3, 10, 5, 2, 4 };
    int N = sizeof(test)/sizeof(int);

    cout << "Size of test array :"  << N << endl;

    cout << "Before sorting : " << endl;
    print(test, N);

    quickSort(test, 0, N-1);

    cout << endl << endl << "After sorting : " << endl;
    print(test, N);

    return 0;
}

/**
 * Quicksort.
 * @param a - The array to be sorted.
 * @param first - The start of the sequence to be sorted.
 * @param last - The end of the sequence to be sorted.
*/
void quickSort( int a[], int first, int last ) 
{
    int pivotElement;

    if(first < last)
    {
        pivotElement = pivot(a, first, last);
        quickSort(a, first, pivotElement-1);
        quickSort(a, pivotElement+1, last);
    }
}

/**
 * Find and return the index of pivot element.
 * @param a - The array.
 * @param first - The start of the sequence.
 * @param last - The end of the sequence.
 * @return - the pivot element
*/
int pivot(int a[], int first, int last) 
{
    int  p = first;
    int pivotElement = a[first];

    for(int i = first+1 ; i <= last ; i++)
    {
        /* If you want to sort the list in the other order, change "<=" to ">" */
        if(a[i] <= pivotElement)
        {
            p++;
            swap(a[i], a[p]);
        }
    }

    swap(a[p], a[first]);

    return p;
}

I have it in Quicksort (C++) . 我在Quicksort(C ++)中有它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM