【问题标题】:Writing Merge Sort Pseudo-Code Procedure in C用 C 编写合并排序伪代码过程
【发布时间】:2018-08-27 00:45:37
【问题描述】:

我一直在经历Introduction to Algorithms,并一直在尝试用C编程语言实现MERGE-SORT算法以更好地理解它。

本书提供了两个伪代码:

虽然我确实了解上述程序,但在实施过程中我一定遗漏了一些东西。

我一定是从伪代码中遗漏了一些东西,但还无法弄清楚。任何关于为什么会发生这种情况的建议将不胜感激。

编辑:更新的代码和输出

/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>

void MERGE(int [], int , int , int );
void printArray(int [], int );
void MERGE_SORT(int [], int , int );

int main(void)
{
   int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
   int arr_size = sizeof(A) / sizeof(A[0]);

   printf("Given array is \n");
   printArray(A, arr_size);

   MERGE_SORT(A, 0, arr_size); //Fixed: Index to start from zero

   printf("\nSorted array is \n");
   printArray(A, arr_size);

   return 0;
}

void MERGE(int A[], int p, int q, int r)
{
   int i = 0;
   int j = 0;
   int n1 = q - p + 1;                  //Computing length of sub-array 1
   int n2 = r - q;                      //Computing length of sub-array 2
   int *L = malloc((n1 + 2) * sizeof(*L + 1));        //Creating Left array
   int *R = malloc((n2 + 2) * sizeof(*R + 1));        //Creating Right array

   for (int i = 0; i <= n1; i++) { //Fixed: <=, i start from 0
       L[i] = A[p + i - 1];
   }
   for (int j = 0; j <= n2; j++) { //Fixed: <=, i start from 0
       R[j] = A[q + j];
   }

   L[n1 + 1] = 99;  //Placing Sentinel at the end of array
   R[n2 + 1] = 99;

   i = 1;
   j = 1;

   /*Prior to the first iteration k = p, so the subarray is empty.
   Both L[i] and R[j] are the smallest elements of their arrays and have not
   been copied back to A*/
   for (int k = p; k <= r; k++) { //Fixed: <=
       if (L[i] <= R[j]) {
           A[k] = L[i];
           i++;
       }
       else { //Fixed: Assignment and not condition check for A[k]
           A[k] = R[j];
           j++;
       }
   }

   free(L);
   free(R);
}

void MERGE_SORT(int A[], int p, int r)
{
   //During first iteration p = 1 & r = 8
   if (p < r) {
       int q = (p + r) / 2;
       MERGE_SORT(A, p, q);
       MERGE_SORT(A, q + 1, r);
       MERGE(A, p, q, r);
   }
}

/* Function to print an array */
void printArray(int Arr[], int size)
{
   int i;
   for (i = 0; i < size; i++)
       printf("%d ", Arr[i]);
   printf("\n");
}

【问题讨论】:

  • 如果您仔细查看伪代码,您会注意到您应该有L[n1+1] = 99;R[n2+1] = 99;。不是L[n1] = 99;R[n2] = 99;
  • @DmitriChubarov,我正在尝试,但是它会导致Heap Corruption Detected,这意味着我正在写入未分配的内存,从而破坏了用于使内存分配器工作的数据结构。伪代码以 1-Indexed Array 表示法编写。
  • @DmitriChubarov,因为在第 3 行写了“让L[1..n1 +1]”,这与L[0..n1] 相同。因此稍后我将标记值写入L[n1]。如果我做错了什么,请纠正我。
  • 你是对的,你必须在整个代码中小心地将索引从 1 更改为 0
  • 你代码开头的函数声明都是错误的。您应该使用参数的类型,而不是名称(或类型和名称,就像在定义中一样)。

标签: c arrays algorithm sorting merge


【解决方案1】:

查看伪代码,发现有些东西写错了。
1. 数组索引从 0 或 1 开始需要注意
2.合并for循环的最后一部分实际上是一个赋值,而不是条件检查。

编辑:已更新代码以修复错误 Stack around the variable A was corrupted

请在此处找到更正后的代码(Lookout for //Fixed for fixs)

/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>

void MERGE(A, p, q, r);
void printArray(Arr, size);
void MERGE_SORT(A, p, r);

int main(void)
{
   int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
   int arr_size = sizeof(A) / sizeof(A[0]);

   printf("Given array is \n");
   printArray(A, arr_size);

   MERGE_SORT(A, 0, arr_size - 1); //Fixed: Index to start from zero, arr_size - 1

   printf("\nSorted array is \n");
   printArray(A, arr_size);

   return 0;
}

void MERGE(int A[], int p, int q, int r)
{
   int i = 0;
   int j = 0;
   int n1 = q - p + 1;                  //Computing length of sub-array 1
   int n2 = r - q;                      //Computing length of sub-array 2
   int *L = malloc((n1+1) * sizeof(*L+1));          //Creating Left array
   int *R = malloc((n2+1) * sizeof(*R+1));          //Creating Right array
   for (int i = 0; i < n1; i++) { //Fixed: i start from 0
       L[i] = A[p + i];

   }
   // int arr_size = sizeof(A) / sizeof(A[0]);
   for (int j = 0; j < n2; j++) { //Fixed: j start from 0
       R[j] = A[q + j + 1];

   }

   L[n1] = 99;  //Placing Sentinel at the end of array
   R[n2] = 99;

   i = 0; //Fixed: i and j to start from 0
   j = 0;

   /*Prior to the first iteration k = p, so the subarray is empty.
   Both L[i] and R[j] are the smallest elements of their arrays and have not
   been copied back to A*/
   for (int k = p; k <= r; k++) { //Fixed: <=
       if (L[i] <= R[j]) {
           A[k] = L[i];
           i++;
       }
       else { //Fixed: Assignment and not condition check for A[k]
        A[k] = R[j];
        j++;
       }
   }

   free(L);
   free(R);
}

void MERGE_SORT(int A[], int p, int r)
{
   //During first iteration p = 1 & r = 8
   if (p < r) {
       int q = (p + r) / 2;
       MERGE_SORT(A, p, q);
       MERGE_SORT(A, q + 1, r);
       MERGE(A, p, q, r);
   }
}

/* Function to print an array */
void printArray(int Arr[], int size)
{
   int i;
   for (i = 0; i < size; i++)
       printf("%d ", Arr[i]);
   printf("\n", size);
}

希望对您有所帮助。
如有任何疑问,请回复。

【讨论】:

  • 非常感谢您提供的有用答案。我看到很多我出错的例子。由于上述更改的某些原因,我得到了Run-time Check Failure #2 - Stack around variable 'A' was corrupted. 我会尝试进一步研究。
  • 我已经更新了代码。在代码中的某些地方,我试图从不存在的数组 A 中获取值。我试图访问导致错误的 A[A.length + 1]。
  • 是的,就是这样。我特别怀念ij 应该被初始化为0!感谢您的帮助。
【解决方案2】:

这是我对您的代码所做的一些更改`

#include<stdlib.h>
#include<stdio.h>

void MERGE(int *A,int p,int q,int r);
void printArray(int *Arr,int size);
void MERGE_SORT(int *A,int p,int r);

int main(void){
    int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
    int arr_size = sizeof(A) / sizeof(A[0]);

    printf("Given array is \n");
    printArray(A, arr_size);

    MERGE_SORT(A, 0, arr_size -1); // pass the indices of the array

    printf("\nSorted array is \n");
    printArray(A, arr_size);

    return 0;
}

void MERGE(int A[], int p, int q, int r){
    int i = 0;
    int j = 0;
    int k; //declair it here
    int n1 = q - p + 1;                //Computing length of sub-array 1
    int n2 = r - q;                    //Computing length of sub-array 2
    int *L = malloc((n1) * sizeof(*L+1));          //Creating Left array
    int *R = malloc((n2) * sizeof(*R+1));       //Creating Right array

    for (int i = 0; i < n1; i++) { //start coping from zero
        L[i] = A[p + i];
   }
   for (int j = 0; j < n2; j++) {
        R[j] = A[q +1 + j];
   }

  // L[n1] = 99;  we won't be needing these as to mark the end we already know the size of arrays
  // R[n2] = 99;

  // i = 1;
  // j = 1;

   /*Prior to the first iteration k = p, so the subarray is empty.
   Both L[i] and R[j] are the smallest elements of their arrays and have not
   been copied back to A*/
    for (k = p; k < r+1 && i < n1 && j<n2; k++) { 
    //i & j checks weather the array has completed or not
        if (L[i] <= R[j]) {
            A[k] = L[i];
            i++;
       }
       else {
           A[k]=R[j];
           j++;
        }
   }
// when one of the array is empty u can copy the rest of the array with out compairing
  while(i<n1)
      A[k++]=L[i++];
  while(j<n2)
      A[k++]=R[j++];


   free(L);
   free(R);
}

void MERGE_SORT(int A[], int p, int r)
{
   //During first iteration p = 1 & r = 8
   if (p < r) {
       int q = (p + r) / 2;
       MERGE_SORT(A, p, q);
       MERGE_SORT(A, q + 1, r);
       MERGE(A, p, q, r);
    }
}

/* Function to print an array */
void printArray(int Arr[], int size){
    int i;
    for (i = 0; i < size; i++)
        printf("%d ", Arr[i]);
        printf("\n");
}`

首先,您没有将正确的参数传递给函数。 那么使用无穷大来表示的概念并不好,因为人们可能想要排序比在这种情况下必须增加无穷大的数字更大的数字,上面给出了另一种方法。 同时,虽然我在这里也解决了你的代码的问题,但数组索引没有正确使用,现在检查一下它的工作:`

#include<stdlib.h>    
#include<stdio.h>

void MERGE(A, p, q, r);
void printArray(Arr, size);
void MERGE_SORT(A, p, r);

int main(void)
{
    int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
    int arr_size = sizeof(A) / sizeof(A[0]);

    printf("Given array is \n");
    printArray(A, arr_size);

    MERGE_SORT(A, 1, arr_size);

    printf("\nSorted array is \n");
    printArray(A, arr_size);

    return 0;
}

void MERGE(int A[], int p, int q, int r)
{
    int i = 0;
    int j = 0;
    int n1 = q - p + 1;                //Computing length of sub-array 1
    int n2 = r - q;                    //Computing length of sub-array 2
    int *L = malloc((n1+1) * sizeof(*L+1));       //Creating Left array
   int *R = malloc((n2+1) * sizeof(*R+1));       //Creating Right array

   for (int i = 1; i < n1; i++) {
       L[i] = A[p + i - 1];
   }
   for (int j = 1; j < n2; j++) {
       R[j] = A[q + j];
   }

   L[n1] = 99;  //Placing Sentinel at the end of array
   R[n2] = 99;

   i = 1;
   j = 1;

   /*Prior to the first iteration k = p, so the subarray is empty.
   Both L[i] and R[j] are the smallest elements of their arrays and have not
   been copied back to A*/
   for (int k = p; k < r; k++) {
       if (L[i] <= R[j]) {
           A[k] = L[i];
           i++;
       }
       else if (A[k] == L[i])
           j++;
   }

   free(L);
   free(R);
}

void MERGE_SORT(int A[], int p, int r)
{
   //During first iteration p = 1 & r = 8
   if (p < r) {
       int q = (p + r) / 2;
       MERGE_SORT(A, p, q);
       MERGE_SORT(A, q + 1, r);
       MERGE(A, p, q, r);
   }
}

/* Function to print an array */

void printArray(int Arr[], int size)
{
   int i;
   for (i = 0; i < size; i++)
       printf("%d ", Arr[i]);

   printf("\n");
}

【讨论】:

  • 感谢您的帮助!我注意到了一些变化,很快就会尝试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-02
  • 2010-11-29
  • 1970-01-01
  • 2019-06-27
  • 1970-01-01
相关资源
最近更新 更多