写了一下归并排序,但是输出的结果并没有排序,结果为2 4 5 7 1 2 ,请大神看一下代码,指明问题出在哪里,感激不尽!!!
#include<stdio.h>
void MERGE_SORT(int a[],int p,int r);
void MERGE(int a[],int p,int q,int r);
void MERGE_SORT(int a[],int p,int r){
if(p<r){
int q = (p + r) / 2;
MERGE_SORT(a,p,q);
MERGE_SORT(a,q+1,r);
MERGE(a,p,q,r);
}
}
void MERGE(int a[],int p,int q,int r){
int i,j,k;
int left[q-p+2],right[r-q+1];
int n1 = q - p + 1;
int n2 = r - q;
for(i=0;i<n1;i++){
left[i] = a[i];
}
for(j=0;j<n2;j++){
right[j] = a[i+j];
}
left[n1] = 1000; //相当于哨兵
right[n2] = 1000; //想当于哨兵
for(i=0,j=0,k=0;k<n1+n2;k++){
if(left[i]<=right[j]){
a[k] = left[i];
i++;
}else{
a[k] = right[j];
j++;
}
}
}
void main(void){
int i;
int a[6] = {2,4,5,7,1,2};
MERGE_SORT(a,0,5);
for(i=0;i<6;i++){
printf("%d ",a[i]);
}
}
排序算法中,for(i=0,j=0,k=0;k<n1+n2;k++){...}的处理,可能会造成子数组访问越界。假设两个有序子数组为{2,4,5}与{1,2,7},如果使用你的排序逻辑,会造成{2,4,5}这个子数组访问越界,所以算法中应增加i<n1和j<n2的判断,各子数组未遍历完的数据,追加到至a[k++]即可。
重写MERGE方法如下:
void MERGE(int a[],int p,int q,int r){
int i,j,k;
int left[q-p+2],right[r-q+1];
int n1 = q-p+1;
int n2 = r-q;
//以下2个for方法的作用是拷贝左右子数组,你在拷贝时就写错了
for(i=0,k=p;i<n1;){
left[i++] = a[k++];
}
for(j=0,k=q+1;j<n2;){
right[j++] = a[k++];
}
//left[n1] = 1000; //相当于哨兵 ------无用
//right[n2] = 1000; //想当于哨兵 ------无用
for(i=0,j=0,k=p;k<p+n1+n2;){
//分别比较2个子数组需要考虑左子数组和右子数组遍历完的情况,不能越界
if((left[i]<=right[j] && i<n1) || j>=n2){
a[k++] = left[i++];
}else if (j<n2){
a[k++] = right[j++];
}
}
}