Поскольку профессор дал вам счет (который, кстати, даже правильно обрабатывает дубликаты), я согласен, что вы должны использовать его, чтобы завершить sh сортировку в дополнительном O (n).
Чтобы сделать это, продолжайте обменивать то, что находится в array[i]
туда, где оно принадлежит, пока array[i]
не содержит то, что принадлежит там. Только , затем go до i+1
. Таким образом, вы знаете, array[0..i]
все содержат то, что принадлежит там (и, следовательно, в все находится там, где оно принадлежит).
for (int i = 0; i < arraySize; i++) {
int belongs_at = counters[i];
while (belongs_at != i) {
swap(array[i], array[belongs_at]);
swap(counters[i], counters[belongs_at]);
belongs_at = counters[i];
}
}
Это O (n), так как каждая итерация внутренний l oop помещает одно (или два) большее значение туда, где он принадлежит, и в целом вы не можете поместить больше n значений туда, где они принадлежат, поэтому в целом вы не можете иметь более n внутренних l oop итерации.
Давайте возьмем {20, 50, 60, 70, 10, 40, 30}
в качестве примера и посмотрим, как выглядит массив в конце каждой итерации for
-l oop:
10 20 60 70 50 40 30 # The while-loop fixed the cycle 20->50->10
10 20 60 70 50 40 30 # 20 was already where it belongs, so nothing happened
10 20 30 40 50 60 70 # The while-loop fixed the cycle 60->40->70->30
10 20 30 40 50 60 70 # 40 was already where it belongs, so nothing happened
10 20 30 40 50 60 70 # 50 was already where it belongs, so nothing happened
10 20 30 40 50 60 70 # 60 was already where it belongs, so nothing happened
10 20 30 40 50 60 70 # 70 was already where it belongs, so nothing happened
Давайте посмотрите пример, где у вас что-то не так: {1, 2, 3, 0}
. Сначала вы поменяете 1
на то, к чему он относится: {2, 1, 3, 0}
. Это по-прежнему оставляет 2
не , где он принадлежит! Вы надеетесь, что это будет исправлено позже. Но этого никогда не произойдет, так как вы потом поменяете 1
на себя, затем 3
на 0
, а затем 3
на себя. Но если в i=0
вы продолжаете, пока array[i]
не содержит того, что там находится, тогда вы не оставите это 2
там опасно неуместным, но исправите это сразу.
Полный код, также в repl.it (это привело к вышеприведенному выводу):
#include <iostream>
using namespace std;
int main() {
// Sample array
int arraySize = 7;
int array[7] = {20, 50, 60, 70, 10, 40, 30};
// Count
int counters[7] = {};
for (int i = 1; i < arraySize; i++)
for (int j = 0; j < i; j++)
if (array[i] < array[j])
counters[j]++;
else
counters[i]++;
// Sort
for (int i = 0; i < arraySize; i++) {
int belongs_at = counters[i];
while (belongs_at != i) {
swap(array[i], array[belongs_at]);
swap(counters[i], counters[belongs_at]);
belongs_at = counters[i];
}
// Show
for (int i = 0; i < arraySize; i++)
cout << array[i] << ' ';
cout << endl;
}
}