【问题标题】:Varying the size of an Array in C在 C 中改变数组的大小
【发布时间】:2016-05-12 12:47:19
【问题描述】:

我编写了一个程序,它生成一个随机数组并使用插入和快速排序算法对其进行排序。该程序还测量每个函数的运行时间。数组的大小在序言中定义为参数化宏L。我的问题是:

如何在一次执行中测试两种排序算法以及不同大小的数组?

我希望我的程序在一次执行中对大小为 L=10, 100, 1000, 500010000 的数组进行排序。我的程序代码详述如下。

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

//Random Array Length
#define MAX 100
#define L 10

void naive_sort(int[]);
void smarter_sort(int[],int,int);
void swap(int[],int,int);
int choose_piv(int[],int,int);

int main(){
    int i, a[L], b[L];
    clock_t tic, toc;

    //Generate an array of random numbers
    for(i=0; i<L; i++)
        a[i]= rand() % (MAX+1);

    //Define b identical to a for fair comparison
    for(i=0; i<L; i++)
        b[i]=a[i];

    //Unsorted Array
    printf("\nUnsorted array:   ");
    for(i=0; i<L; i++)
            printf("%d    ", a[i]);

    //Insertion Sort (1e)
    tic = clock();
    naive_sort(a);
    printf("\nInsertion Sort:   ");
            for(i=0; i<L; i++)
                printf("%d    ", a[i]);
    toc = clock();
    printf("  (Runtime: %f seconds)\n", (double)(toc-tic)/CLOCKS_PER_SEC);

    //Quicksort (1f)
    tic = clock();
    smarter_sort(b,0,L-1);
    printf("Quicksort:        ");
            for(i=0; i<L; i++)
                printf("%d    ", b[i]);
    toc = clock();
   printf("  (Runtime: %f seconds)\n", (double)(toc-tic)/CLOCKS_PER_SEC);

   return 0;
}

void naive_sort(int a[]){
    int i, j, t;
    for(i=1; i < L; i++){
        t=a[i];
        j=i-1;
        while((t < a[j]) && (j >= 0)){
            a[j+1] = a[j];
            j--;
        }
        a[j+1]=t;
    }
}

void smarter_sort(int a[], int l, int r){
    if(r > l){
        int piv = choose_piv(a, l, r);
        smarter_sort(a, l, piv-1);
        smarter_sort(a, piv+1, r);
    }
}

void swap(int a[], int i, int j){
    int t=a[i];
    a[i]=a[j];
    a[j]=t;
}

int choose_piv(int a[], int l, int r){
    int pL = l, pR = r;
    int piv = l;
    while (pL < pR){
        while(a[pL] < a[piv])
            pL++;
        while(a[pR] > a[piv])
            pR--;
        if(pL < pR)
            swap(a, pL, pR);
    }
    swap(a, piv, pR);
    return pR;
}

如有任何反馈,我将不胜感激。


编辑:我按照建议修改了代码,它适用于小值。但是对于快速排序案例L=100 及其他情况,我没有得到任何输出:

如您所见,我得到的少数输出为零。代码有什么问题?

/*
 * Task 1, question h
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Random Array Length
#define MAX 100

void perf_routine(int);
void naive_sort(int[],int);
void smarter_sort(int[],int,int);
void swap(int[],int,int);
int choose_piv(int[],int,int);

int main(){
    perf_routine(10);
    perf_routine(100);
    perf_routine(1000);
    perf_routine(5000);
    perf_routine(10000);
   return 0;
}

void perf_routine(int L){
    int i, a[L], b[L];
        clock_t tic, toc;

        printf("Arrays of Length %d:\n", L);

        //Generate an array of random numbers
        for(i=0; i<L; i++)
            a[i]= rand() % (MAX+1);

        //Define b identical to a for fair comparison
        for(i=0; i<L; i++)
            b[i]=a[i];

        //Insertion Sort (1e)
        tic = clock();
        naive_sort(a, L);
        toc = clock();
        printf("Insertion Sort Runtime: %f seconds\n", (double)(toc-tic)/CLOCKS_PER_SEC);

        //Quicksort (1f)
        tic = clock();
        smarter_sort(b,0,L-1);
        toc = clock();
       printf("Quicksort Runtime: %f seconds\n", (double)(toc-tic)/CLOCKS_PER_SEC);
}

void naive_sort(int a[], int L){
    int i, j, t;
    for(i=1; i < L; i++){
        t=a[i];
        j=i-1;
        while((t < a[j]) && (j >= 0)){
            a[j+1] = a[j];
            j--;
        }
        a[j+1]=t;
    }
}

void smarter_sort(int a[], int l, int r){
    if(r > l){
        int piv = choose_piv(a, l, r);
        smarter_sort(a, l, piv-1);
        smarter_sort(a, piv+1, r);
    }
}

void swap(int a[], int i, int j){
    int t=a[i];
    a[i]=a[j];
    a[j]=t;
}

int choose_piv(int a[], int l, int r){
    int pL = l, pR = r;
    int piv = l;
    while (pL < pR){
        while(a[pL] < a[piv])
            pL++;
        while(a[pR] > a[piv])
            pR--;
        if(pL < pR)
            swap(a, pL, pR);
    }
    swap(a, piv, pR);
    return pR;
}

【问题讨论】:

  • 将数组大小作为函数的附加参数,而不是全局常量。
  • @MOehm 我正在考虑做类似的事情,但我不知道该怎么做。你能澄清一下吗?
  • 总的来说,您可能需要查看标准 C qsort 函数原型,了解如何以通用方式编写此类函数接口。
  • 在朴素排序中,反转 while 循环的条件,因此它永远不会尝试计算 a[j] if j
  • @Puck 你的意思是换个顺序?

标签: c arrays sorting


【解决方案1】:

我会在每个函数中在参数中给出数组的长度,并确保您不要尝试到达数组之外的元素,例如交换将变为:

int swap(int *a, int length, int i, int j)
{
    if(i>=length || j>=length)
        return -1;
    int t=a[i];
    a[i]=a[j];
    a[j]=t;
    return 0;
}

还要注意返回 -1 或 0 表示失败。将其应用于其余代码,您将拥有可以应用于任何数组的内容。

【讨论】:

  • 但是如何改变主函数中创建的随机数组呢?
  • 这里没问题,如果你想在变量中有长度,使用malloc:int len = 5678; int * a = malloc(len*sizeof(int)); for(int i=0; i
  • 如果我把main函数的所有内容都放在另一个void函数perf(int L)中,并在main中为L的不同值实例化它会不会出错?为什么我必须修改swap
  • @LukeCollins:您可以将核心代码放入一个单独的函数中,然后使用长度参数perf(L) 调用该函数。但是您仍然必须将数组长度传达给您调用的所有函数,因为L 将是perf 的本地地址。这意味着所有数组函数都应该将数组数据和长度作为参数。 (swap 的修改可以说是没有必要的。它只是为您提供了强制执行数组边界的可能性。在您的示例中,我将保留 swap 原样。)
  • 是的,实际上 smarter_sort 已经在其参数中考虑了数组的长度。您只需将长度添加为 naive_sort 的参数即可使其正确。但是仍然有理由修改其他函数:确保不会发生分段错误,即使您在另一个上下文中使用这些函数(例如交换函数可能对其他事情有用)
【解决方案2】:

当数组传递给函数时,它们作为(或“衰减”)指针传递给它们的第一个元素。没有办法知道数组的大小。

因此,将实际长度作为附加参数传递给函数是很常见的。下面是一个简单排序的示例,其中包含三个不同大小的数组。

当然,必须注意保持数组和长度同步。传递太大的长度可能会导致未定义的行为。例如,在下面的示例中调用fill(tiny, LARGE) 可能会导致灾难。

(旁白:一个数组可能有一个最大长度或容量和一个实际长度。例如,如果你想从一个文件中读取最多十个数字,你必须传递一个长度为 10 的数组,但如果只有四个读取数字时,您在此处处理两个附加参数:可能的数组长度 10 和实际长度 4。不过,这里不是这种情况。)

嗯,就这样吧。所有三个数组函数都具有相同的签名:它们接受一个数组及其长度。

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

void sort(int a[], size_t len)
{
    size_t i, j;

    for (i = 1; i < len; i++) {
        int t = a[i];

        j = i - 1;

        while (j >= 0 && t < a[j]) {
            a[j + 1] = a[j];
            j--;
        }

        a[j + 1] = t;
    }
}

void fill(int a[], size_t len)
{
    size_t i;

    for (i = 0; i < len; i++) {
        a[i] = rand() / (1.0 + RAND_MAX) * 100;
    }
}

void print(int a[], size_t len)
{
    size_t i;

    for (i = 0; i < len; i++) {
        if (i) printf(", ");
        printf("%d", a[i]);
    }

    puts("");
}

#define TINY 3
#define MEDIUM 10
#define LARGE 15

int main(void)
{
    int tiny[TINY];
    int medium[MEDIUM];
    int large[LARGE];

    srand(time(NULL));

    fill(tiny, TINY);
    fill(medium, MEDIUM);
    fill(large, LARGE);

    print(tiny, TINY);
    print(medium, MEDIUM);
    print(large, LARGE);

    sort(tiny, TINY);
    sort(medium, MEDIUM);
    sort(large, LARGE);

    print(tiny, TINY);
    print(medium, MEDIUM);
    print(large, LARGE);

    return 0;
}

【讨论】:

    猜你喜欢
    • 2012-04-17
    • 2021-02-03
    • 1970-01-01
    • 2015-06-06
    • 2019-12-02
    • 2017-07-03
    • 1970-01-01
    • 2021-10-19
    相关资源
    最近更新 更多