【问题标题】:Finding max element in an array查找数组中的最大元素
【发布时间】:2017-06-27 19:16:56
【问题描述】:

我有一个数组,我必须找到其中最大的元素,告诉它出现了多少次以及在什么位置。我必须使用指针和动态内存分配。

随机填充数组时不起作用,但手动填充时效果很好。

这段代码可以正常工作:

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

void max_elem (int n, float* vett) {

  int i=0, *pos, p=0, n_ele_pos;
  float max=*(vett);

  pos=(int*)malloc(sizeof(int));
  if (pos==NULL) {printf("BUM\n" ); exit (0);}
  *(pos)=0;
  for (i=1; i<n; i++) {
    if (*(vett+i)>max) {
      max=*(vett+i);
      p=0;
      *(pos)=i;
    }
    else  if (*(vett+i)==max) {
      p++;
      *(pos+p)=i;
    }
  }
  if (p==0) {
    printf("\nmax element is %f, in position %d  ", max, *pos+1);
  }
  else {
    printf("\n max element %f, %d times in position\n", max, p+1);
    for (i=0; i<p+1; i++) {
    printf("%d  ", *(pos+i)+1);
    }
  }
  printf("\n\n");
  free(pos);
}

int main()
{
    int i,n;
    float *element;
    printf("\n\n Pointer : Find the largest element using Dynamic Memory Allocation :\n");
    printf("-------------------------------------------------------------------------\n");
    printf(" Input total number of elements(1 to 100): ");
    scanf("%d",&n);
    element=(float*)calloc(n,sizeof(float));  // Memory is allocated for 'n' elements
    if(element==NULL)
    {
        printf(" No memory is allocated.");
        exit(0);
    }
    printf("\n");
    for(i=0;i<n;++i)
    {
       printf(" Number %d: ",i+1);
       scanf("%f",element+i);
    }

    max_elem (n, element);
    return 0;
}

但下一个没有。我必须用我决定的特定范围内的随机数填充数组,即使是整数随机数的十进制到十进制极值(是的,我知道这实际上没有多大意义)。用十进制数字填充时搜索有时效果很好,而整数我只有 0。

代码如下:

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

float rand_float (float *, float *);
int rand_int (float *, float *);
void min_max(float *, float *, float *, float *);
int num_intero(float);
void max_elem (int, float*);

int main () {

  int n, i, t;
  float x1, x2;

  printf ("array size:\t");
  scanf ("%d", &n);
  printf("\ninterval extremes:\t");
  scanf ("%f %f", &x1, &x2);
  do {
    printf("1 for decimal random numbers, 2 for integers:\t");
    scanf("%d", &t);
  } while (t!=1 && t!=2);
  srand(time(NULL));
  switch (t) {

    case 1 :  {

      float *vett;

      vett=(float*)calloc(n, sizeof(float));
      if (vett==NULL) {printf("BUM\n" ); exit (0);}
      for (i=0;i<n;i++) {
        *(vett+i)=rand_float(&x1, &x2);
        printf("%d__\t%10f\n", i, *(vett+i));
      }
      max_elem (n, vett);
      free(vett);

      break;
    }
    case 2 :  {

      int *vett;

      vett=(int*)calloc(n, sizeof(int));
      if (vett==NULL) {printf("BUM\n" ); exit (0);}
      for (i=0; i<n; i++) {
        *(vett+i)=rand_int(&x1, &x2);
        printf("%d__\t%10d\n", i, *(vett+i));
      }
      max_elem (n, (float*)vett);
      free (vett);

      break;
    }
  }

  return 0;
}

void min_max (float*x1, float *x2, float *min, float *max) {

  if (*x1<*x2) {
    *min=*x1;
    *max=*x2;
  }
  else {
    *min=*x2;
    *max=*x1;
  }
}

float rand_float (float *x1, float *x2) {

  float min, max;

  min_max(x1, x2, &min, &max);
  return ((max-min)*(float)rand()/RAND_MAX)+min;
}

int num_intero (float min) {

  if (min/(int)min==1)
    return 1; //e' intero
  else return 0;
}

int rand_int (float *x1, float *x2) {

  float min, max;

  min_max(x1, x2, &min, &max);
  if ((int)min==(int)max) {
    return (int)min;
  }
  else  if (min==0) {
          return (rand()%((int)(max)+1));
        }
        else  if (max==0) {
                return (rand()%((int)(-min)+1)+min);  //funziona anche con ((int)(min)-1)+min
              }
              else if ((int)min!=(int)max) {
                      if (num_intero (min)==1) {
                        return (rand()%((int)(max-min)+1)+min);
                      }
                      else  if (num_intero (max)==0) {
                              return (rand()%((int)(max-min))+min+1);
                            }
                            else return (rand()%((int)(max-min)+1)+min+1);
              }
}

void max_elem (int n, float* vett) {

  int i=0, *pos, p=0, n_ele_pos;
  float max=*(vett);

  pos=(int*)malloc(sizeof(int));
  if (pos==NULL) {printf("BUM\n" ); exit (0);}
  *(pos)=0;
  for (i=1; i<n; i++) {
    if (*(vett+i)>max) {
      max=*(vett+i);
      p=0;
      *(pos)=i;
    }
    else  if (*(vett+i)==max) {
      p++;
      *(pos+p)=i;
    }
  }
  if (p==0) {
    printf("\nmax element is %f, in position %d  ", max, *pos+1);
  }
  else {
    printf("\n max element %f, %d times in position\n", max, p+1);
    for (i=0; i<p+1; i++) {
    printf("%d  ", *(pos+i)+1);
    }
  }
  printf("\n\n");
  free(pos);
}

此外,当数组很大时,我会出现这样的运行时错误,而第一个代码则没有: error

示例: first code, second code and integers error(bottom)

我在 Ubuntu 16.04 (gnome) 上使用 gcc 和 atom 编辑器。 谢谢和抱歉。

【问题讨论】:

  • pos 只分配给一个int 的大小。如果 p 曾经 > 0 则 *(pos+p)=i; 是未定义的行为
  • max_elem 在我看来似乎有点过大,无法在数组中找到最大元素... 为什么需要动态 分配像pos 这样的局部变量?添加更多可能的错误?
  • @yano 所以我必须使用 calloc 吗?抱歉,我是新手,没听懂你说的。
  • 我建议你学习一些调试技巧。首先一步一步地写下你希望你的代码做什么。然后使用调试器或 cout 语句来验证您的代码实际执行的操作。最后,找出您所期望的结果与实际结果不同的原因。
  • @EugeneSh。我使用了动态分配,因为我不想创建一个 n 大小的静态数组

标签: c pointers random casting dynamic-allocation


【解决方案1】:

让问题简单一点。

我有一个数组,我必须找到其中最大的元素,告诉它出现了多少次以及在什么位置。我必须使用指针和动态内存分配。

因此,在最坏的情况下,当您的数组包含相同的元素时,您将拥有与元素相同数量的位置。如果您不需要针对内存使用优化代码,那么您可以分配两个长度相同的数组(一个用于数字,一个用于位置)。

下一个简化选项是在填充数组时找到最大值。 (无论 fillig 方法使用读取用户输入的随机数,您都可以在将元素一个接一个地插入到数组中时确定最大值。)

也许您可以找到更多简化选项,但有了这些,您就可以将max_elem 函数抛在脑后:

#include <stdio.h>
#include <stdlib.h>
#include <float.h> /* for FLT_MIN */

void assert_alloc(void* ptr) {
    if(ptr == NULL) {
        printf("No memory is allocated.\n");
        exit(0);
    }
}

int main() {
    int i, n, k = 0, *positions;
    float max = FLT_MIN, *elements; /* max is now the smallest possible float */

    printf("Input total number of elements(1 to 100): ");
    scanf("%d", &n);

    /* allocate array of same size for numbers and for positions */
    elements = (float*)calloc(n, sizeof(float));
    assert_alloc(elements);

    positions = (int*)calloc(n, sizeof(int));
    assert_alloc(positions);

    /* fill the array and find the maximum meanwhile */
    for(i = 0; i < n; ++i) {
        printf("Number %d: ", i + 1);
        scanf("%f", elements + i);

        if(max < *(elements + i))
            max = *(elements + i);
    }
    printf("\nmax element is %f, ", max); /* max is already known */

    /* find the positions of the maximal number */
    for(i = 0; i < n; ++i) {
        if(max == *(elements + i)) {
            *(positions + k) = i;
            k++;
        }
    }

    /* print the positions of the maximal number */
    if(k > 1) {
        printf("%d times in position\n", k);
        for(i = 0; i < k; i++)
            printf("%d  ", *(positions + i) + 1);
    }
    else {
        printf("in position %d", *positions + 1);
    }    
    printf("\n");

    free(elements);
    free(positions);
    return 0;
}

我检查了您的代码,它有两个问题。主要问题在于您的 max_elem 函数内部,您必须使用 calloc 或将 sizeof(int) 乘以 n

pos = (int*)malloc(n * sizeof(int));

完成此操作后,您的第二个示例将适用于 float 类型。它不适用于int 类型的原因是您的max_elem 只接受float 指针。您将int 指针作为max_elem(n, (float*)vett); 传递给该函数,这是错误的,因为pointer arithmeticsintfloat 在内存中以不同的方式表示。要解决此问题,请将您的 vett 指针声明为 float*,无论您是否将使用 intfloat 值填充它。

Live Demo

【讨论】:

  • 谢谢!无论如何,这是另一种编码方式。你能帮我修复我的代码,我认为的“方式”吗?
  • 我编辑了我的答案,并指出了您第二个示例的主要问题。
  • 我认为这还没有结束。我已经进行了很多测试(所有测试都具有相同的输入)并且似乎在 yoursmine 出现超过 1 次“max”时我们得到错误或不完整的输出。无论如何,现在我可以使用大数组了。
  • 我也测试过,对我来说效果很好。如我所见,your 示例失败,因为floatprecision。由于打印数字的数量,您可能会在输出中看到相同的数字,但相比之下它们可能是不同的数字。
  • 要将float 值四舍五入到小数点后的特定位数,请使用roundf
猜你喜欢
  • 1970-01-01
  • 2021-06-20
  • 2013-12-15
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
  • 2014-07-21
  • 2010-12-12
相关资源
最近更新 更多