是否按多个标准进行快速排序

Make QuickSort sort by multiple criteria?

本文关键字:快速排序 标准 是否      更新时间:2023-10-16

是否有按多个条件进行快速排序的方法?例如,我有一组边。每条边都有一个源、目的地和长度。我想先把长度较小的边放在我的数组中。但如果长度相同,我想用一个较小的源顶点进行排序。如果这些源顶点相同,我想按两个目标顶点中较小的一个进行排序。

例如:

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]等操作,因为成员都是int。

我认为这(以及你提交的代码)应该可以完成你想要的任务。

如果你有稳定性问题,那是因为快速排序不稳定。你可以通过添加更多的条件来避免lhs==rhs的发生。或者,您可以尝试Mergesort

坦率地说,我对Quick排序没有太多经验,但你的impl看起来确实与Wikipedias原地算法明显不同。例如,您的枢轴根本不移动。你能检查一下是否有问题吗?


编辑

查看您的链接后

看起来链接的算法也将pivot用作值,而不是索引(就像您所做的那样)。它在语法上看起来与您的相同,直到您考虑到您的枢轴值可能会移动,之后您的枢轴索引将指向其他

int pivot = arr[(left + right) / 2];

这有帮助吗?

EDIT:以下是就地快速排序的伪代码:http://en.wikipedia.org/wiki/Quicksort#In-位置版本

这与代码的不同之处在于,数据透视是一个值(左右值的平均值),而不是一个索引。

如果您正在寻找一个简单的非最优解决方案,请按目标顶点合并整个列表,然后按原点顶点合并整个名单,然后按边长度合并整个名单。这利用了mergesort是一种稳定的排序算法,并且运行时间为边数O(E)的事实。