【问题标题】:Problem with my quicksort, it doesn't sort correctly我的快速排序有问题,它没有正确排序
【发布时间】:2019-05-27 12:46:04
【问题描述】:

好的,我正在尝试制作 Prima 算法,所以我需要对边数组进行排序,我尝试在这里使用快速排序,但它没有按我的计划工作。

#include <iostream>


using namespace std;

void Sort (int arr[100][4], int m, int l) {
     int i,j,x,v;

    i=m;
    j=l;
    x=(i+j)/2;
    do
    {
        while (((arr[i][3]<arr[x][3]))and(i<=l)) i++;
        while (((arr[j][3]>arr[x][3]))and(j>=m)) j--;
        if (i<=j)
        {
        v=arr[i][1];
        arr[i][1]=arr[j][1];
        arr[j][1]=v;
        v=arr[i][2];
        arr[i][2]=arr[j][2];
        arr[j][2]=v;
        v=arr[i][3];
        arr[i][3]=arr[j][3];
        arr[j][3]=v;
        i++;
        j--;
        }
    }
    while (i<=j);
    if (i<l) Sort(arr,i,l);
    if (m<j) Sort(arr,m,j);
}

int main () {
    int i,x,y,z,n,m;
    int a[100][4];
    fill(&a[0][0],&a[0][0]+400,0);
    cout<<"Enter number of nodes and edges\n";
    cin>>n>>m;
    cout<<"Enter edges and their weights\n";
    for (i=0;i<m;i++) {
        cin>>x>>y>>z;
        a[i][1]=min(x,y);
        a[i][2]=max(x,y);
        a[i][3]=z;
        }
    Sort (a,0,m-1);
    for (i=0;i<m;i++) {
        cout<<i+1<<") "<<a[i][1]<<' '<<a[i][2]<<' '<<a[i][3]<<endl;
    }
    return 0;
}

我写的是

5 10

1 2 4

1 3 7

4 1 5

5 1 8

2 3 3

2 4 6

2 5 6

3 4 8

3 5 2

4 5 4

我得到的是 1) 3 5 2

2) 2 3 3

3) 1 4 5

4) 1 2 4

5) 4 5 4

6) 2 5 6

7) 2 4 6

8) 1 3 7

9) 1 5 8

10) 3 4 8

我不明白为什么 5 比 4 领先。希望你能帮上忙。

【问题讨论】:

  • 你为什么不使用库 qsort。
  • @Yogesh 我不确定它应该如何与 multidim 一起使用。数组,我也确定在我的一个...
  • @Yogesh 建议qsort 用于标记c++ 的问题并没有真正的帮助。但是,您可能想使用std::sort
  • @Неизвестный Неизвестный 关于不确定如何使用它,您可以编写自己的比较器函数,用于比较两个元素,将指针传递给多维数组并以您想要的方式访问- 用于比较。检查stackoverflow.com/questions/50084423/…。感谢您自己写作的精神。
  • @datell 是的,有点想念它。

标签: c++ quicksort


【解决方案1】:

您选择(子)数组中间的枢轴元素,这很好,但是您在运行分区循环时将它留在那个位置,并依赖它来留在那里,这是不行的。使用您的方法,在普通分区过程中,枢轴可能会被交换到不同的位置,之后分区的其余部分将基于交换到枢轴原始位置的键,这可能会有所不同。

通常的方法是首先将枢轴元素交换到数组的一端或另一端,对数组的其余部分进行分区,然后将枢轴交换到正确的位置,如通过分区过程发现的那样。

【讨论】:

  • 如果使用Hoare partition scheme,则无需将枢轴元素交换到数组的一端或另一端。相反,问题在于枢轴值(而不是索引)应该存储在临时变量中。
  • @rcgldr,我没有说必须将枢轴交换到一端,我说这是通常。当然还有其他选择。
  • OP 的代码是 Hoare 分区方案的一种变体,其中中间元素的值作为枢轴,并且枢轴不移动。等于枢轴值的元素可能会出现在任一分区中。
  • 不,@rcgldr,OP 的分区方案是 Hoare 分区的 broken 变体,其中枢轴作为(初始)中间元素。特别是,将枢轴留在原来的位置并依靠它保持在那里的组合是破碎的,而不是前者本身。我再次断言 通常 方法,正如我最常看到并且似乎最常见的方法,就是我所描述的方法。它确实是 Hoare 分区的一个完全有效的实现,但当然不是唯一有效的实现。
  • 是的,OP 的代码被破坏了,因为它应该使用枢轴值,而不是枢轴索引,但我还没有看到任何将枢轴从中间移动到的 Hoare 分区方案示例任一端。其中大部分与wiki article 中的类似。 Lomuto 分区方案确实使用任一端作为枢轴位置,或者将枢轴交换到任一端,然后在分区步骤完成时再次交换以正确的枢轴位置。 Hoare 可能会在任一分区中留下等于枢轴的元素。
【解决方案2】:

更改代码以使用枢轴值而不是枢轴索引,并进行一些修复以使其更像传统的 Hoare 分区方案:

    i=m-1;
    j=l+1;
    x=arr[(i+j)/2][3];
    while(1)
    {
        while (arr[++i][3] < x);
        while (arr[--j][3] > x);
        if(i >= j)
            return j;
        // ...

【讨论】:

    猜你喜欢
    • 2011-11-03
    • 2015-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-31
    • 2011-08-11
    • 2015-03-13
    相关资源
    最近更新 更多