Есть ли способ сделать быструю сортировку по нескольким условиям? Например, у меня есть набор ребер. Каждое ребро имеет источник, назначение и длину. Сначала я хочу поместить ребро с меньшей длиной в массив. Но если длины одинаковы, я хочу отсортировать их по меньшей исходной вершине. Если эти исходные вершины одинаковы, я хочу отсортировать по меньшей из двух конечных вершин.
Например:
4 (источник) 2 (пункт назначения) 3 (длина)
1 (источник) 5 (пункт назначения) 3 (длина)
Поскольку они оба имеют одинаковую длину, мы смотрим на исходную вершину. Поскольку второе ребро меньше первого, мы меняем их местами, потому что сравниваем по исходной вершине.
Ниже приведена моя быстрая сортировка, и я, честно говоря, не уверен, почему она сортируется неправильно. Если есть способ сделать быструю сортировку менее эффективной, но более стабильной, я бы с удовольствием принял предложения!
void quickSort(edge *e, int left, int right)
{
int i = left, j = right;
int temp, temp1, temp2;
int pivot = (left + right)/2;
while(i <= j)
{
while(e[i] < e[pivot])
i++;
while(e[pivot] < e[j])
j--;
if(i <= j)
{
temp = e[i].getLength();
temp1 = e[i].getEdgeSrc();
temp2 = e[i].getEdgeDes();
e[i].setLength(e[j].getLength());
e[i].setEdgeSrc(e[j].getEdgeSrc());
e[i].setEdgeDes(e[j].getEdgeDes());
e[j].setLength(temp);
e[j].setEdgeSrc(temp1);
e[j].setEdgeDes(temp2);
i++;
j--;
} //if statement
}///while loop
if(left < j)
quickSort(e, left, j);
if(i < right)
quickSort(e, i, right);
}
Моя сортировка условий:
bool edge::operator<(const edge &other) const
{
if (length < other.length)
return true;
else if ((length == other.length) && (source < other.source))
return true;
else if((length == other.length) && (source == other.source) && (destination < other.destination))
return true;
return false;
}
Опять же, если кто-нибудь знает способ правильно сделать эту быструю сортировку, уменьшив сложность времени, но сделав ее стабильной, я с радостью приму любые предложения! Спасибо! Любая помощь?
Изменить: Вот как я вызвал мою быструю сортировку. Я вызвал его, основываясь на количестве прочитанных ребер.
quickSort(e, 0, edges-1); //-1 because if you put in edges, it'd go past the bounds of the array
РЕДАКТИРОВАТЬ: когда я пытаюсь вставить что-то вроде этого в моем алгоритме:
0 1 1
0 3 1
1 3 1
2 5 1
4 10 1
4 8 1
10 8 1
11 6 2
11 7 2
6 7 1
9 6 1
9 7 1
Это вывод:
0 1 1
0 3 1
1 3 1
2 5 1
4 8 1
4 10 1
6 7 1
6 9 1
8 10 1 <- должно быть ниже 7 9 1
7 9 1 <- должно быть выше 8 10 1
6 11 2
7 11 2
Так чище написать
if (length != other.length)
return length<other.length;
if ( source != other.source)
return source < other.source;
return destination < other.destination;
Вы также должны быть в состоянии сделать temp = e[i]
и так далее, так как все участники являются целыми.
Это (и код, который вы представили) должно сделать задачу, которую вы хотите, я думаю.
Если у вас есть проблемы со стабильностью, это потому, что быстрая сортировка не стабильна. Вы можете обойти это, добавив больше условий, чтобы lhs==rhs
не бывает В качестве альтернативы вы можете попробовать Сортировка слиянием
Откровенно говоря, у меня нет особого опыта работы с быстрой сортировкой, но ваши впечатления заметно отличаются от Алгоритм Википедии на месте. Например, ваш стержень вообще не двигается. Не могли бы вы проверить, если это проблема?
Посмотрев на ваша ссылка
Похоже, что связанный алгоритм также использует pivot в качестве значения, а не в качестве индекса (как вы делаете). Он выглядит синтаксически идентично вашему, пока вы не решите, что значение вашего пивота может сместиться, после чего ваш индекс сводки будет указывать на что-то другое
int pivot = arr[(left + right) / 2];
Это помогает?
РЕДАКТИРОВАТЬ: Вот псевдокод для быстрой сортировки на месте: http://en.wikipedia.org/wiki/Quicksort#In-place_version
Это отличается от вашего кода тем, что ось представляет собой значение (среднее значение для левого и правого значений), а не индекс.
Если вы ищете простое неоптимальное решение, объедините сортировку всего списка по целевой вершине, затем объедините сортировку всего списка по исходной вершине, а затем объедините сортировку всего списка по длине ребра. Это использует тот факт, что сортировка слиянием является устойчивым алгоритмом сортировки и имеет время выполнения O (E) по числу ребер.