递归地获得数组中的第k个最小元素

时间:2014-10-13 06:07:49

标签: c++ arrays algorithm recursion partition

我正在尝试从我的教科书中提供的伪代码“翻译”此算法。我的程序一直在崩溃,我不确定我的实现在哪里出错了。这是图像中的伪代码,我的代码位于其下方:enter image description here

int kSmallFirst (int k, int anArray[], int first, int last) {
    int pivotIndex = 0;

    if (k < pivotIndex - first + 1)
        return kSmallFirst(k, anArray, first, pivotIndex - 1);
    else if (k == pivotIndex - first + 1)
        return pivotIndex;
    else
        return kSmallFirst(k - (pivotIndex - first + 1), anArray, pivotIndex + 1, last);
}

int main () {
    int i = 0;
    int arr[512];
    fstream data;
    data.open("data.txt");

    while (!data.eof()) {
        data >> arr[i];
        i++;
    }

    data.close();

    cout << kSmallFirst(42, arr, 0, i-1);

    return 0;
}

非常感谢!

3 个答案:

答案 0 :(得分:4)

问题是:您没有实现算法的主要部分,这在您的书中用 italic 字体描述:

  

选择一个透视值“p”形式'anArray [first..last]'

     

将'anArray [first..last]'的值分为'p'

这两行不是评论!它们是伪代码,您将转换为C / C ++ ,以使您的代码能够执行您希望它执行的操作。

答案 1 :(得分:2)

请注意,kSmallFirst从不使用anArray,因此与JoriO所说的相反,这不是输入问题。即使尝试使用范围main,也会将范围[0 .. -1]作为kSmallFirst的{​​{1}}和first传递。

您需要了解算法正在做什么,否则CiaPan提到您将无法实现最重要的部分。

last是:

  1. 接纳由kSmallanArray
  2. 定义的first分区
  3. lastpivotIndex
  4. 之间的anArray分区中选择first
  5. 将所有小于last的元素移到anArray[pivotIndex]以下且所有大于pivotIndex的元素移到anArray[pivotIndex]以上
  6. 这将定义pivotIndex的下一对分区,从anArrayfirst的分区以及从pivotIndexpivotIndex的分区
  7. last将对包含kSmall元素的范围进行递归
  8. 考虑到这一点,重写k将产生:

    kSmall

    我相信你会注意到if语句中的数学与书不同。我选择使用#include <algorithm> #include <functional> int kSmall(int k, int* anArray, int first, int last){ int p = anArray[(last - first) / 2 + first]; // Choose a pivot value from anArray[first .. last] int* pivotIndex = std::partition(anArray + first, anArray + last, std::bind2nd(std::less<int>(), p)); // Partition the values of anArray around p if(k < pivotIndex - anArray){ return kSmall(k, anArray, first, pivotIndex - anArray); } else if(k == pivotIndex - anArray){ return pivotIndex - anArray; } else{ return kSmall(k, anArray, pivotIndex - anArray, last); } } 参数来实现kSmall,本书选择使用int参数。

答案 2 :(得分:0)

您选择枢轴索引值是错误的。

由于这是递归,因此您需要为每次调用更新数据透视。

让它更通用。

kSmallFirst函数中,

使用 pivotIndex = first ,而不是 pivotIndex = 0