【问题标题】:3-way Merge Sort C program3路归并排序C程序
【发布时间】:2017-10-01 15:38:10
【问题描述】:

我试图为学校项目“升级”我的正常合并排序。但是我的新代码似乎没有应有的协同作用

所以我有一个 MergeSort3way 函数,该函数将输入的数组拆分为 3 个子数组,然后它会调用自身直到排序完成,但输出离正确的很远。

void Mergesort3way(int A[],int n){
//Sort array A with divition of 3
int B[n/3];
int C[n/3];
int D[n/3];
int i,c;

if(n>1){
    for(i=0;i<n/3;i++){
        B[i]=A[i];
    }
    for(i=n/3;i<2*n/3;i++){
        c= i-n/3;
        C[c]=A[i];
    }
    for(i=2*n/3;i<n;i++){
        c=i-(2*n/3);
        D[c]=A[i];
    }

Mergesort3way(B,n/3);
Mergesort3way(C,n/3);
Mergesort3way(D,n/3);
int bn = sizeof(B)/sizeof(B[0]);
int cn = sizeof(C)/sizeof(C[0]);
int dn = sizeof(D)/sizeof(D[0]);
Merge3way(B,C,D,A,bn,cn,dn);    
}

}

然后merge3way将它们组合成1个单一的排序数组

void Merge3way(int B[],int C[],int D[],int A[],int p,int q,int r){
int i=0,j=0,u=0,k=0;

while(i<p && j<q && u<r){
    if(B[i]<C[j]){
        if(B[i]<D[u]){
            A[k]=D[u];
            u++;
        }else{
            A[k]=B[i];
            i++;
        }
    }else{
        if(C[j]<D[u]){
          A[k]=D[u];
          u++;  
        }else{
          A[k]=C[j];
          j++;
        }
    }
    k++;
 }
int all = p+q+r;    
if(i==p){
    if(u==r){
     while(j<q && k<all){
        A[k]=C[j];
        k++;
        j++;            
     } 
    }else{
        while(u<r && k<all){
        A[k]=D[u];
        k++;
        u++;
        }
    }
}else if(j==q){
    if(u==r){
     while(i<p && k<all){
        A[k]=B[i];
        k++;
        i++;            
     } 
}
  }
} 

您能否建议我任何解决方案,以便我可以按照它应该进行的排序,我已经尝试了 2 多个小时的修改,结果始终相同。在此先感谢,因为这是我第一次使用该网站,所以请不要感到难过。

【问题讨论】:

  • 不要数组CD,不是n/3元素,而是2*n/3 - n/3n - 2*n/3元素,分别?另外:2*n/3 并不总是等于2*(n/3)
  • ...如果n 不是3 的倍数,则定义的三个数组(每个数组都包含n/3 元素)将不会在它们之间总共包含n 元素。
  • 我建议使用单个无限循环,例如while (1) { }。在循环体中,找出三个中最好的,记住一两个列表可能是空的。将最好的项目添加到输出中,并增加相应的索引。在循环结束时,检查三个列表是否都为空,如果是,则break 循环。

标签: c sorting merge


【解决方案1】:

如果这应该是升序排序,那么如果 (B[i]

一旦到达 B[]、C[] 或 D[] 的末尾,代码需要切换到其余两个的 2 路合并。您可以交换数组名称(实际上是被调用函数中的指针),以简化这一点,因此 2 路合并使用 B 和 C。如果首先到达 B 的末尾,则 B = C 和 C = D。如果先到达 C 的结尾,然后 C = D。如果先到达 D 的结尾,则不需要数组(指针)赋值。

一旦到达 B 或 C 的末尾,则只需复制剩余的子数组。

为了索引的一致命名,我会使用 k 表示 D[],使用 u 表示 A[],但这不会造成问题。

【讨论】:

    【解决方案2】:

    我认为你的这部分代码,

    while(i<p && j<q && u<r){
        if(B[i]<C[j]){
            if(B[i]<D[u]){
                A[k]=D[u];
                u++;
            }else{
                A[k]=B[i];
                i++;
            }
        }else{
            if(C[j]<D[u]){
              A[k]=D[u];
              u++;  
            }else{
              A[k]=C[j];
              j++;
            }
        }
        k++;
     }
    

    需要改成这样:

    while(i<p && j<q && u<r){
        if(B[i]<C[j]){
            if(B[i]<D[u]){
                A[k]=B[i];
                i++;
            }else{
                A[k]=D[u];
                u++;
            }
        }else{
            if(C[j]<D[u]){
              A[k]=C[j];
              j++;  
            }else{
              A[k]=D[u];
              u++;
            }
        }
        k++;
     }
    

    你的这部分代码:

    if(i==p){
        if(u==r){
         while(j<q && k<all){
            A[k]=C[j];
            k++;
            j++;            
         } 
        }else{
            while(u<r && k<all){
            A[k]=D[u];
            k++;
            u++;
            }
        }
    }else if(j==q){
        if(u==r){
         while(i<p && k<all){
            A[k]=B[i];
            k++;
    

    需要像这样更改为 something

    if (i < p && j < q){
      # append the result of normal merge of remaining elements of B and C to A
    } else if (j < q && u < r) {
      # append the result of normal merge of remaining elements of C and D to A
    } else if (i < p && u < r) {
      # append the result of normal merge of remaining elements of B and D to A
    } else {
          if (i == p && j == q && u < r){
             # append remaining elements of D to A
          } else if (i < p && j == q && u == r){
             # append remaining elements of B to A
          } else if (i == p && j < q && u == r){
             # append remaining elements of C to A
          }
    }
    

    虽然,正如你所说,你有一个 normal mergesort,你正在尝试修改它,那么,如果在对数组的每个 1/3rd 部分进行排序之后,像这样:

    Mergesort3way(B,n/3);
    Mergesort3way(C,n/3);
    Mergesort3way(D,n/3);
    

    您首先使用normal mergesort 组合两个排序部分中的任何一个,然后使用normal mergesort 再次将它们的结果与第三部分组合。例如:首先使用normal mergesortsorted Bsorted C合并,让我们称他们的结果为BmC,然后使用normal mergesort将他们的结果BmCsorted D合并,最终得到合并结果:@987654337 @。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-08
      • 2012-01-03
      • 2012-08-22
      • 1970-01-01
      相关资源
      最近更新 更多