Редактировать (29.05.2015): я упустил требование о поддержании порядка появления, поэтому приведенный ниже ответ не удовлетворяет всем требованиям вопроса.Однако я оставляю исходный ответ для общего интереса.
Это специальная версия очень важной подпрограммы быстрой сортировки, известной как «разделение».Определение: массив A, имеющий N числовых записей, делится на значение K по индексу p, если A [i] = K для p <= j <N, если только всезаписи меньше K (что означает p = N) или не меньше K (что означает p = 0).Для рассматриваемой проблемы мы разделим массив вокруг K = 0. </p>
Вы можете разбить несортированный массив на любое значение K за O (n) раз, получая доступ к каждой записи в массиве только один раз, используя O(1) дополнительная память.Неформально вы проходите массив с обоих концов, перемещая значения, которые находятся не на той стороне.Произведите своп, когда на каждой стороне массива будет найдено одно неуместное значение, затем продолжите шаг внутрь.Теперь код C ++:
// Assume array A[] has size N
int K = 0; // For particular example partitioning positive and negative numbers
int i = 0, j = N-1; // position markers, start at first and last entries
while(1) { // Break condition inside loop
while(i < N && A[i] < K) i++; // Increase i until A[i] >= K
while(j >= 0 && A[j] >= K) j--; // Decrease j until A[j] < K
if(i < j)
swap(A[i],A[j]);
else
break;
}
// A[] is now partitioned, A[0]...A[j] < K, unless i==0 (meaning all entries >= K).
Обратите внимание, что если все элементы равны K (в данном случае, нулю), i никогда не увеличивается и j = 0 в конце.В постановке проблемы предполагается, что этого никогда не произойдет.Разделение очень быстрое и эффективное, и именно благодаря этой эффективности быстрая сортировка является самой популярной процедурой сортировки для больших массивов.Функция подкачки может быть std :: swap в C ++, или вы можете легко написать свою собственную:
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
Или просто для удовольствия, числа можно поменять местами без временной памяти, но помните о переполнении:
// This code swaps a and b with no extra space. Watch out for overflow!
a -= b;
b += a;
a = b - a;
Существует много вариантов разделения для особых случаев, например, трехстороннее разделение для [elements K].Алгоритм быстрой сортировки вызывает разделение рекурсивно, и значение раздела K обычно является первой записью в текущем подмассиве или вычисляется из нескольких записей (например, медиана трех).См. Учебники: Алгоритмы Седжвика и Уэйна (4-е изд., Стр. 288) или Искусство компьютерного программирования, вып.3 Кнутом (2-е изд., Стр. 113).