У меня есть вектор из N чисел, и я хочу найти n-е число в массиве. Я использую вариант быстрой сортировки, но время от времени у меня возникает проблема с бесконечными циклами, и я думаю, что, если наибольшее число является единственным вариантом в двух массивах. Число может появляться в массиве много раз, так что, если, например, я выберу 10 для N и я хочу найти 1-е наибольшее число, я могу получить {9,9} в левом массиве, что приведет к бесконечному циклу. Что я могу сделать, чтобы исправить это? Вот мой код
#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <vector>
using namespace std;
int partition(int n, int arrsize, vector<int> intarr); //pass vector by val
int main() {
int n, N;
cout << "Please enter n: " << endl;
cin >> n;
cout << "Please enter N: " << endl;
cin >> N;
vector<int> array;
srand(time(NULL));
for(i=0; i < N; i++) {
array.push_back(1 + rand() % N);
cout << array.at(i) << ", ";
}
//Get the nth largest value of array[N]
int arraylen = array.size();
cout << "\nArraylen is " << arraylen << endl;
int result = partition(n, arraylen, array);
cout << "The " << n << "th largest number is: " << result <<endl;
return 0;
}
int partition(int n, int arrsize, vector<int> intarr) {
//1. Get a random value from the array:
int random = rand() % arrsize;
int pivot = intarr.at(random);
//2. Partition the array into 2 halves left < pivot > right
vector<int> left;
vector<int> right;
for(int j=0; j < arrsize; j++) {
if (intarr[j] >= pivot)
left.push_back(intarr[j]);
else if (intarr.at(j) < pivot)
right.push_back(intarr[j]);
else continue;
}
cout << "\n \n" << "Left = ";
for(int k = 0; k < left.size(); k++) {
cout << left.at(k) << ", ";
}
cout << endl << "Right = ";
for(int k = 0; k < right.size(); k++) {
cout << right.at(k) << ", ";
}
int leftlen = left.size();
int rightlen = right.size();
if (n < leftlen)
return partition(n, leftlen, left);
else if (n > (arrsize - rightlen)) {
n = n - (leftlen);
return partition(n, rightlen, right);
}
else return pivot;
}
Так как вы все равно создаете новые векторы (я полагаю, потому что вы не хотите изменять входной вектор), вы также можете просто избегать помещения элемента pivot влево или вправо. В этом случае, если стержень окажется элементом, который вы ищете, он будет пойман else return pivot
и если вы столкнетесь с вырожденным случаем, когда раздел — это все равные элементы, то ничто не будет помещено ни в левую, ни в правую часть, и единственное значение раздела будет возвращено правильно.
Способ быстрой сортировки позволяет избежать этой проблемы — никогда не помещать элемент pivot в сортируемые субвекторы; следовательно, даже если один из векторов окажется одним и тем же элементом, он все равно окажется короче, чем был. Это тонкость с быстрой сортировкой, которая редко объясняется хорошо, хотя Седжвик обсуждает способы улучшения производительности быстрой сортировки на векторах со многими повторяющимися элементами.
Проверка того, что любой из подмассивов пуст, поможет обнаружить бесконечный цикл, а также сбой в некоторых других случаях.
int leftlen = left.size();
int rightlen = right.size();
if (leftlen == 0 || rightlen == 0) /* break processing */
редактировать Бесконечный цикл возможен, только если один из массивов равен 0, а другой заполнен тем же значением.