使用指针合并int数组

时间:2010-07-06 14:32:24

标签: c pointers merge sorting

对于学校,我必须仅使用指针编程合并排序。 我几乎尝试了所有的东西,但我无法让它发挥作用。

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

#define num_elementi(array) (sizeof(array)/sizeof(array[0]))

void selsort(int arr[],int n);
void swap(int * a, int * b);
void print(int arr[],int n);
void insort(int arr[],int n);
void mergesort(int arr[],int *p,int *u);
void merge(int arr[],int * p, int * q,int * u);

int main(int argc, char *argv[]){
    int arr[]={99,12,14,65,2,7,54,78,5,1,43,59,88,28,61};
    int n=num_elementi(arr);
    printf("numero elementi array: %d\n",n);
    print(arr,n);
    printf("numero elementi array: %d\n",n);    
    mergesort(arr,&arr[0],&arr[n-1]);
    print(arr,n);
    system("pause");
}

void selsort(int arr[],int n){
    int *i,*j;
    for(i=arr;i<&arr[n-1];i++){
        for(j=i+1;j<&arr[n];j++){
            if(*j<*i)swap(i,j);;
        }

    }
}

void swap(int * a, int * b){
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

void print(int arr[],int n){
    int * p=arr;
    for(p;p<&arr[n];p++)printf("%d ",*p);
    printf("\n");
}

void insort(int arr[],int n){
    int *i,*k;
    for(i=&arr[1];i<&arr[n];i++){
        k=i-1;
        while(k>=&arr[0]&& *k>*(k+1)){
            swap(k,k+1);
            k=k-1;
        }
    }
}


void mergesort(int arr[],int *p,int *u){
    if (p<u){
        int *q=((u-p)/2)+p;
        mergesort(arr,p,q);
        mergesort(arr,q,u-1);
        merge(arr,p,q,u);
    }

}

void merge(int arr[],int * p, int * q,int * u){
    int arr1[u-p]; //inizializzazione array di dimensioni utili
    int * i=p; //puntatore al primo elemento di arr
    int *j=q+1; //puntatore al elemento di mezzo +1 di arr
    int *k= arr1; //puntatore al primo elemento di arr1
    if (u-p==1){ 
        if (*u<*p){
            swap(u,p);
        }
        return;
    }
    while(i<q && j<u){
        if(*i<*j){ 
            *k=*i;
            i=i+1;
        }
        else{
            *k=*j;
            j=j+1;
        }
        k=k+1;
    }
    while(i<q){*k=*i;i++;k++;}
    while(j<u){*k=*j;j++;k++;}

    i=p;
    k=arr1;
    for(i,k;i<&arr[u-p];i++,k++){
        *i=*k;
    }
}

有人可以解释一下我做错了吗?非常感谢你!!

PS:请原谅我非常糟糕的英语。

编辑 Maciej Hehl建议的新代码

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

#define num_elementi(array) (sizeof(array)/sizeof(array[0]))

void swap(int * a, int * b);
void print(int arr[],int n);
void mergesort(int arr[],int * arr_begin,int * arr_end);
void merge(int * destination, int * r1_begin, int * r1_end, int * r2_begin, int * r2_end);

int main(int argc, char *argv[]){
    int arr[]={99,12,14,65,2,7,54,78,5,1,43,59,88,28,61};
    int n=num_elementi(arr);
    print(arr,n);  
    mergesort(arr,&arr[0],&arr[n-1]);
    print(arr,n);
    system("pause");
}

void swap(int * a, int * b){
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
}

void print(int arr[],int n){
    int * p=arr;
    for(p;p<&arr[n];p++)printf("%d ",*p);
    printf("\n");
}

void mergesort(int arr[],int * arr_begin,int * arr_end){
    int * med,*arr1,*p,*p1;
    printf("i'm doing something\n");
    if(arr_begin<arr_end){
        med=arr[arr_end-arr_begin]/2+arr_begin;
        mergesort(arr,arr_begin,med);
        mergesort(arr,med+1,arr_end);
        arr1=malloc((arr_end-arr_begin)*sizeof(int));
        printf("msort calls ended begin merge\n");
        merge(arr1,arr_begin,med,med+1,arr_end);
        for(p=arr,p1=arr1;p<arr_end&&p1<&arr1[arr_end-arr_begin];p++,p1++){
            *p=*p1;
        }
    }

}

void merge(int * destination, int * r1_begin, int * r1_end, int * r2_begin, int * r2_end){
    int *pdest=destination;
    if (r1_end-r1_begin==1){ 
        if (*r1_end<*r1_begin){
            swap(r1_end,r1_begin);
        }
        return;
    }
    if (r2_end-r2_begin==1){ 
        if (*r2_end<*r2_begin){
            swap(r2_end,r2_begin);
        }
        return;
    }
    while(r1_begin<=r1_end&&r2_begin<=r2_end){
        if(*r1_begin<*r2_begin){
            *pdest=*r1_begin;
            r1_begin++;
        }
        else{
            *pdest=*r2_begin;
            r2_begin++;
        }
        pdest++;
    }
    while(r1_begin<r1_end){
        *pdest=*r1_begin;
        r1_begin++;pdest++;        
    }
    while(r2_begin<r2_end){
        *pdest=*r2_begin;
        r2_begin++;pdest++;
    }

}

2 个答案:

答案 0 :(得分:3)

修改

你的编辑让我原来的答案(下面)对其他读者毫无意义:)哦,好吧......

首先要确定你的beginend指针是否定义范围[开始,结束]或[开始,结束]。我建议第一个选择因为它在C ++库中使用。如果您同意,那么电话

mergesort(arr,&arr[0],&arr[n]);

是对的。只有在您决定时,您才需要将&arr[n]更改为&arr[n-1],您希望指针beginend定义范围[begin,end],我建议不要这样做

事实上,指针beginend足以对范围进行排序,而mergesort函数不需要第一个参数。

med的计算不正确

med=arr[arr_end-arr_begin]/2+arr_begin;

在之前的版本中是正确的(变量名为q)

以下调用也不正确

mergesort(arr,arr_begin,med);
mergesort(arr,med+1,arr_end);

第一次调用应该对范围[arr_begin,med]进行排序,而不是[arr_begin,med](*med不属于该范围),因此第二次调用应该从{{开始对范围进行排序1}}。

arr1的分配是正确的,这要归功于差异med等于元素的数量。这是选择范围[开始,结束]而不是[开始,结束]的优势。但是,如果您在使用后释放了已分配的内存,那将会很不错。

合并调用不正确,就像上面对end - begin的调用一样。第二个范围sholuld从mergesort开始,因为med指向第一个范围,而不是它的最后一个元素。

med的实施过于复杂。你不必交换任何东西。您只需从两个范围中获取元素并将它们复制到目标。这三个while循环开始我原来的帖子(下面)就足够了,但要注意条件。

我再次重复merge过去第一个范围,med过去第二个范围。考虑到这一点,您应该使用arr_end还是<=运营商?


我不喜欢以下代码中条件<i<=qj<=ui<q的不一致性:

j<u

您可以像这样调用您的mergesort:

while(i<=q && j<=u){
    if(*i<*j){ 
        *k=*i;
        i=i+1;
    }
    else{
        *k=*j;
        j=j+1;
    }
    k=k+1;
}
while(i<q){*k=*i;i++;k++;}
while(j<u){*k=*j;j++;k++;}

这意味着,mergesort(arr,&arr[0],&arr[n]); 是一个指针,指向数组的最后一个元素之后的点。换句话说,你似乎想到了你的指针,比如迭代器ubegin,它们定义范围[begin,end] - end属于范围,但是{{1不是,

在你写的*begin的定义中

*end

与上述假设不一致。如果mergesort,则int *q=((u-p)/2)+p; mergesort(arr,p,q); mergesort(arr,q+1,u); 可能相等q

p表示对范围[p,q)进行排序(u == p+1超出范围) mergesort(arr,p,q);表示对范围[q + 1,u)进行排序(q超出范围)

如果您使用指针表示范围是一致的,那么您永远不会以这种方式触及元素mergesort(arr,q+1,u);

将范围视为[begin,end]而不是[begin,end](在第二种情况下u是范围的一部分)与在C ++中使用迭代器的方式一致,但它不是强制性的。您也可以使用指针来定义范围,但在这种情况下,您必须将调用*q更改为*end在这两种情况下,您必须重新考虑开头引用的代码中的条件

这是一个家庭作业,所以我不会为你解决它,但这里有一点暗示,这可能有助于思考它。重新定义您的mergesort(arr,&arr[0],&arr[n]);,因此明确合并需要2个范围:

mergesort(arr,&arr[0],&arr[n-1]);

并思考如何使用它。稍后你可以简化一些事情。您并不真正需要目标参数,并且您不必复制所有合并元素。您可以先复制一个范围,然后直接合并到目标中,从第一个范围的副本和第二个范围中获取元素。

答案 1 :(得分:1)

在主要情况下,如果您在每次调用printf("*** n=%d\n", n)之前添加print,您会注意到,在第二次调用之前,输出为n=61。也就是说,您正在对阵列进行良好排序,但是当您再次打印它时,您将打印61个数字 你也可以注意到61是数组中最大的数字,n是在arr之后定义的,所以narr将在连续的内存地址中在堆栈中。我认为在n函数调用期间mergesoft被覆盖了 实际上,当您使用mergesoft致电&arr[n]时,会发生覆盖。数组的最后一个元素的索引为n-1。第n个索引实际上对应于n变量。将通话更改为:mergesort(arr,&arr[0],&arr[n-1]);