Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ quickselect算法因元素重复而失败_C++_Algorithm_Sorting_C++11 - Fatal编程技术网

C++ quickselect算法因元素重复而失败

C++ quickselect算法因元素重复而失败,c++,algorithm,sorting,c++11,C++,Algorithm,Sorting,C++11,我已经实现了快速选择算法 我有一个问题,当我在数组中使用重复项时,我的算法最终会陷入一个无止境的循环 你能帮我把它修好吗 期望的复杂度是O(n),最坏情况是O(n^2) #包括 #包括 #包括 #包括 使用名称空间std; int-rand_划分(向量&a,int-left,int-right){ int pivotIndex=left+(rand()%(right-left)); //int m=left+(right-left)/2;//…测试算法…此时没有随机数 int pivot=a[p

我已经实现了快速选择算法

我有一个问题,当我在数组中使用重复项时,我的算法最终会陷入一个无止境的循环

你能帮我把它修好吗

期望的复杂度是O(n),最坏情况是O(n^2)

#包括
#包括
#包括
#包括
使用名称空间std;
int-rand_划分(向量&a,int-left,int-right){
int pivotIndex=left+(rand()%(right-left));
//int m=left+(right-left)/2;//…测试算法…此时没有随机数
int pivot=a[pivotIndex];
int i=左;
int j=右;
做{
while(a[i]pivot
while(a[j]>pivot)j--;//查找正确的元素您的代码中有几个问题

  • 首先,在函数
    quick_select()
    中,您直接将
    pivotIndex
    n
    进行比较。由于
    left
    并不总是0,您应该将
    n
    与左部分的长度进行比较,左部分的长度等于
    pivotIndex-left+1
  • n>length
    时,您只需递归调用
    quick\u select(a,pivotIndex+1,right,n)
    ,此时,这意味着整个向量的第n个元素位于它的右侧,它是向量右侧的第(n-(pivotIndex-left+1))个元素。代码应该是
    quick\u select(a,数据透视索引+1,右,n-(数据透视索引-左+1))
    (n是基于一的)
  • 似乎您使用的是Hoare的分区算法,并且实现不正确。即使它有效,当Hoare分区终止时,它返回一个值j,使得
    a[p…j]≤ A[j+1…r]
    ,但我们想要
    A[p…j-1]≤ A[j]≤ 一个[j+1…r]
    quick\u select()
    中。所以我使用了
    rand\u partition()
    ,它基于我写的Lomuto的分区算法
下面是固定的
quick_select()
,它返回向量的第N个(注意,N是一个基于的)最小元素:

int quick_select(vector<int> &a, int left, int right, int n)
{
    if ( left == right ) 
        return a[left];
    int pivotIndex = partition(a, left, right);

    int length = pivotIndex - left + 1;
    if ( length == n) 
        return a[pivotIndex];
    else if ( n < length ) 
        return quick_select(a, left, pivotIndex - 1, n);
    else 
        return quick_select(a, pivotIndex + 1, right, n - length);
}
首先调用
srand()
初始化随机数生成器,以便在调用
rand()
时可以得到类似随机数的数字
用于测试上述功能的驱动程序:

int main()
{
    int A1[] = {1, 0, 3, 5, 0, 8, 6, 0, 9, 0};
    vector<int> a(A1, A1 + 10);
    cout << "6st order element " << quick_select(a, 0, 9, 6) << endl;
    vector<int> b(A1, A1 + 10); // note that the vector is modified by quick_select()
    cout << "7nd order element " << quick_select(b, 0, 9, 7) << endl;
    vector<int> c(A1, A1 + 10);
    cout << "8rd order element " << quick_select(c, 0, 9, 8) << endl;
    vector<int> d(A1, A1 + 10);
    cout << "9th order element " << quick_select(d, 0, 9, 9) << endl;
    vector<int> e(A1, A1 + 10);
    cout << "10th order element " << quick_select(e, 0, 9, 10) << endl;
}
intmain()
{
INTA1[]={1,0,3,5,0,8,6,0,9,0};
向量a(A1,A1+10);

要测试您的算法,请一次对所有这些进行排序:{}、{0}、{0,1}、{1,0}、{0,0}、{0,1,2}、{0,2,1}、{1,0,2}、{1,2,0}、{2,0,1}、{2,0,1}、{0,0,0}、{0,0,1}、{0,1,0,1}、{。如果它能正确地对所有这些进行排序,那么您可能已经完成了。我看到的第一件事是,在某些情况下,您迭代通过开始和/或结束,寻找要交换的节点。我看到的第二件事是,当存在重复的pivot时,您的分区似乎陷入了无限循环中。当它循环时,请附加调试呃,暂停它,然后一步一步地看它为什么在循环中。@Xarn:这是一个选择,而不是排序。它可能(通常是)有O(n)复杂性。@JerryCoffin我把它看作是排序,注意到。
int rand_partition(vector<int> &arr, int start, int end)
{
    int pivot_index = start + rand() % (end - start + 1);
    int pivot = arr[pivot_index];

    swap(arr[pivot_index], arr[end]); // swap random pivot to end.
    pivot_index = end;
    int i = start -1;

    for(int j = start; j <= end - 1; j++)
    {
        if(arr[j] <= pivot)
        {
            i++;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i + 1], arr[pivot_index]); // swap back the pivot

    return i + 1;
}
int main()
{
    int A1[] = {1, 0, 3, 5, 0, 8, 6, 0, 9, 0};
    vector<int> a(A1, A1 + 10);
    cout << "6st order element " << quick_select(a, 0, 9, 6) << endl;
    vector<int> b(A1, A1 + 10); // note that the vector is modified by quick_select()
    cout << "7nd order element " << quick_select(b, 0, 9, 7) << endl;
    vector<int> c(A1, A1 + 10);
    cout << "8rd order element " << quick_select(c, 0, 9, 8) << endl;
    vector<int> d(A1, A1 + 10);
    cout << "9th order element " << quick_select(d, 0, 9, 9) << endl;
    vector<int> e(A1, A1 + 10);
    cout << "10th order element " << quick_select(e, 0, 9, 10) << endl;
}