【问题标题】:Sorting of an array using merge sort使用归并排序对数组进行排序
【发布时间】:2014-12-11 18:40:06
【问题描述】:

我已经在 c 中实现了合并排序,尽管代码似乎是正确的,但代码并没有给我排序数组,而是返回给它的相同数组,这意味着我的合并函数不起作用

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

void re_sort(int arr[],int size);
void merge(int left[],int right[],int arr[],int rightlen,int leftlen);

int main(void)
{ 
  int a[10];
  int n;

  printf("enter the number\n");

  scanf("%d",&n);

    printf("enter the elements\n");
    for(int i=0;i<n;i++)

      {  
         scanf("%d",&a[i]);
      }

    re_sort(a,n);          //merge sort using recursion  

    printf("the sorted list is:\n");
    for(int i=0;i<n;i++)

      {  printf("%d\t",a[i]);

      }


    return 0;
}

void re_sort(int arr[],int size)

{  int mid,*left,*right;
   int k=0;
  if(size<2)            
    return; 

  else 
  mid=size/2;
  left=(int*)(malloc(mid*(sizeof(int))));          // two sub arrays left and right 
  right=(int*)(malloc((size-mid)*(sizeof(int))));

  for(int i=0;i<mid;i++)
  { 
    left[i]=arr[k++];
  }

  for(int j=0;j<(size-mid);j++)
  { 
    right[j]=arr[k++];
  }

  re_sort(left,mid);                 //recursion until size becomes less than 2
  re_sort(right,size-mid);
  merge(left,right,arr,size-mid,mid); //both the elements in left and right are merged



}
void merge(int left[],int right[],int arr1[],int rightlen,int leftlen)

{   int arr[100];
    int k=0,i=0,j=0;
    while(i<leftlen && j<rightlen)
    { 
      if(left[i]<= right[j])

      arr[k++]=left[i++];

      else 

      arr[k++]=right[j++];

    }

    while(i<leftlen)
    {
        arr[k++]=left[i++];
    } 
    while(j<rightlen)

    { 
       arr[k++]=right[j++];
    }

    for(int l=0;l<(rightlen+leftlen);l++)
    { 
      arr1[l]=arr[l];
    }
    free(left);
    free(right);
}

【问题讨论】:

  • arr[l]=arr1[l]; 之后呢??
  • 每次递归调用都会泄漏内存...
  • 你也没有传递指向数组的指针,你只是传递数组?所以你实际上并没有改变任何值。除非我遗漏了什么,这是完全有可能的。
  • @SouravGhosh 是的,谢谢修复,哈哈
  • @dragosht 好的,我可以防止这种情况,因为如果我创建 2 个子数组,总会有内存泄漏

标签: c sorting mergesort


【解决方案1】:

这里

  if(left[i]<= right[j])
      arr[k++]=left[i++];
  else 
      arr[k++]=left[j++];

最后一个left 应该是right

不管怎样,你free你的记忆malloc-ed...在哪里?

【讨论】:

  • 同样arr[l]=arr1[l];应该是arr1[l]=arr[l];
【解决方案2】:

malloc 在每次递归调用时为每个子数组创建一个新缓冲区是一个非常糟糕的主意。请记住,malloc 是相当昂贵的操作,而free 的成本甚至比malloc 高得多!

递归拆分产生的子数组不重叠(合并跨越两个合并部分的结果除外)。因此,合并结果一次不需要超过一个缓冲区并且合并不会干扰任何其他合并(除了它是子合并的那些)范围)。因此,只需创建整个输入数组的单个副本,并交替使用这两个数组作为递归合并的源位置和目标位置:

void merge( int dst[], int src[], int idx1, int idx2, int end2)
{
    int idx = idx1;
    int end1 = idx2;

    while(idx1 < end1 && idx2 < end2)
        dst[idx++] = src[idx1] <= src[idx2] ? src[idx1++] : src[idx2++];
    while(idx1 < end1)
        dst[idx++] = src[idx1++];
    while(idx2 < end2)
        dst[idx++] = src[idx2++];
}

void mrgsrt( int dst[], int src[], int begin, int len)
{
    if(len == 1)
        dst[begin] = src[begin];
    if(len > 1) {
        int mid = len/2;
        mrgsrt(src, dst, begin, mid);
        mrgsrt(src, dst, begin+mid, len-mid);
        merge(dst, src, begin, begin+mid, begin+len);
    }
}

void sort( int a[], int len)
{
  int *tmp;
  if((tmp = malloc(len*sizeof(*a))) != NULL) {
    memcpy(tmp, a, len*sizeof(*a));
    mrgsrt(a, tmp, 0, len);
    free(tmp);
  }
}

【讨论】:

    猜你喜欢
    • 2021-08-19
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2011-03-12
    • 2011-02-25
    • 2016-01-01
    相关资源
    最近更新 更多