【问题标题】:How to find top 6 elements in an array in C如何在C中找到数组中的前6个元素
【发布时间】:2015-01-30 00:14:52
【问题描述】:

我正在尝试从具有它们的排序号的数组中查找前 6 个元素。

    int x=0;

for (int k = 0; k < 6; k++) //
{
    for (i = 1; i <= 90; i++)
    {
        if (sorted[k] < holder[i] && i >= x)
        {
            sorted[k] = holder[i];
            x = i; //
        }
    }
}

但这不起作用。我希望它给我像 43->7 15 ->3 等这样的输出。

【问题讨论】:

  • 只需对数组进行排序,获取前 6 个元素,然后从原始数组中找到这些元素的索引。
  • “前 6 名”是什么意思?他们的“订货号”是多少? holdersorted 包含什么?您正在寻找的输出示例是什么?
  • @wallyk Holder 包含所有元素。 Sorted 是一个包含 6 个元素的数组。前 6 个是指最大的 6 个元素。例如,订购号是如果最大的元素是持有人[46],那么 46 是我们的订购号。
  • 你可以使用partial sorting
  • 我是新手@MikeKobit 你能帮我提供我给出的代码吗

标签: c sorting


【解决方案1】:

好久没写C了,这里有一个简单的解决方案,原地修改数组,使用选择排序选择数组中k最高的数字,并将它们移到前面。它保留一个与数字最初所在位置相对应的索引数组,并对它应用相同的交换。

#include <stdio.h>
#define ELEMENTS 10

void main(void)
{
    // example input for execution
    int numbers[10] = {9,4,5,1,8,2,3,6,0,7};
    // tracks ordering of indices
    int indexes[10] = {0,1,2,3,4,5,6,7,8,9};
    int k = 6;

    int i, j;
    int max, temp;

    // Partial selection sort, move k max elements to front
    for (i = 0; i < k; i++)
    {
        max = i;
        // Find next max index
        for (j = i+1; j < ELEMENTS; j++)
        {
            if (numbers[j] > numbers[max])  {
                max = j;
            }
        }
        // Swap numbers in input array
        temp = numbers[i];
        numbers[i] = numbers[max];
        numbers[max] = temp;
        // Swap indexes in tracking array
        temp = indexes[i];
        indexes[i] = indexes[max];
        indexes[max] = temp;
    }

    for (i = 0; i < k; i++) {
        printf("%d -> %d\n", indexes[i], numbers[i]);
    }
}

还有输出:

0 -> 9
4 -> 8
9 -> 7
7 -> 6
2 -> 5
1 -> 4

【讨论】:

    【解决方案2】:

    这是我给你的答案。

    我希望有人能提供一些建设性的批评。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int numbers[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
        int *ptrNumbers[10];
        int i=0;
        for(; i < 10; i++){
            ptrNumbers[i] = &numbers[i]; // assign the addresses
        }
    
        int topSix[6];
    
        int topSixIndex=0;
        for(; topSixIndex < 6; topSixIndex++){
            int **best = NULL; // Pointer to the pointer to the value.
    
            int checkIndex=0;
            for(; checkIndex < 10; checkIndex++){
                if(ptrNumbers[checkIndex] != NULL){
                    if(!best){
                        /* best is not yet defined */
                        best = &ptrNumbers[checkIndex];
                        // best now points to the pointer for numbers[checkIndex]
                    }else if(*ptrNumbers[checkIndex] > **best){
                        // this else if statement could be attached to the main if as
                        // an or condition, but I've separated it for readability.
                        best = &ptrNumbers[checkIndex];
                        // best now points to the pointer for numbers[checkIndex]
                    }
                }
            }
            // assign the topSix position and flag the ptrNumbers
            topSix[topSixIndex] = **best;
            *best = NULL;
        }
    
        // now we'll print the numbers
        for(topSixIndex = 0; topSixIndex < 6; topSixIndex++){
            printf("%d\n", topSix[topSixIndex]);
        }
    
        return 0;
    }
    

    程序基本上是这样工作的:给定一个包含十个数字的数组,构造第二个数组来存放指向这 10 个数字的指针。然后构造第三个数组来存放前 6 个数字的值。然后初始化一个 for 循环,循环 6 次以找到最高的未记录值。当通过循环指针数组找到最大值时,将该值分配给前六个数组的下一个索引。添加该值后,指向前六个值的指针数组的索引然后分配给 NULL。这充当一个标志,确保不会再次添加该值。最后,所有的数字都打印出来了。

    运行这段代码后,我收到的输出是:

    9
    8
    7
    6
    5
    4
    

    编辑:作为注释,订购号可以存储在第二个数组中。您只需跟踪最高值的checkIndex,然后将其分配给包含索引值的第二个数组。

    【讨论】:

    • 没问题。很高兴它可以提供帮助。我很抱歉,因为它有点乱。
    • 有趣的想法,但我认为它的性能很糟糕。您可以简单地复制数据,并通过将元素设置为INT_MIN 将其从考虑中删除,而不是指针数组。这使得它在下一次比较为假(除非所有其他值也是INT_MIN)。
    • 在实践中,更高效的算法是可能的(接触数据的频率较低)。如果您只想要一个大数组中的几个高元素,请在循环时保留一个优先级队列。如果您想要上半部分或前三分之一,请进行部分排序。
    • @PeterCordes,哦,是的。这个答案是几年前我还在学习 C 时写的。我当然不会支持这种超级高效的解决方案。看来我对玩指针更感兴趣,但谁知道我当时在想什么。尽管如此,我猜你回应了“一些建设性的批评” ;-)
    【解决方案3】:

    也许您不是在寻找仅代码的答案,但这会起作用:

    #include <limits.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    // return index of max element
    int max_index( int* vec, int sz )
    {
        int idx, max, i;
    
        if(!sz) return -1;
    
        idx = 0;
        max = vec[0];
    
        for(i=1; i<sz; ++i)
        {
            if( vec[i] > max )
            {
                max = vec[i];
                idx = i;
            }
        }
    
        return idx;
    }
    
    // return indexes of N top elements
    void top( int* vec, int sz, int* out_vec, int N )
    {
        int i, *tmp, idx;
    
        tmp = (int*) malloc( sz*sizeof(int) );
        memcpy( tmp, vec, sz*sizeof(int) );
    
        for(i=0; i<N; ++i )
        {
            idx = max_index(tmp,sz);
            out_vec[i]=idx;
            tmp[idx] = INT_MIN;
        }
    
        free(tmp);
    }
    

    现场观看here

    【讨论】:

    • 其实我正在寻找一个纯代码的答案。但是我们可以坚持使用C吗?我不会在这个项目中使用 C++,所以你能帮帮我吗?
    • @sp2danny,OP 正在寻找 C 答案,而不是 C++。不过,向量将是一个很好的 C++ 解决方案。
    【解决方案4】:

    创建一个包含数据和索引的结构数组,然后对其进行排序并选取第一个或最后 6 个元素进行输出。

    【讨论】:

      【解决方案5】:

      假设给你一个数组numbers。然后创建一个与数字大小相同的数组indexes,使其值等于它们的索引。这是一个插图:

      numbers = [ 1, 7, 3, 9, 2, 0 ]
      indexes = [ 0, 1, 2, 3, 4, 5 ]
      

      按降序对numbers 进行排序,对indexes 执行相同的操作。最后,你应该得到这样的结果:

      numbers = [ 9, 7, 3, 2, 1, 0 ]
      indexes = [ 3, 1, 2, 4, 0, 5 ]
      

      最后,您需要做的就是处理这些数组的前六个元素。


      #include <stdio.h>
      
      #define TRUE 1
      #define FALSE 0
      
      int contains(int array[], int array_size, int value)
      {
          int i;
      
          for (i = 0; i < array_size; i++)
          {
              if (array[i] == value)
              {
                  return TRUE;
              }
          }
      
          return FALSE;
      }
      
      int main()
      {
          int numbers[] = { 1, 7, 3, 9, 2, 0 };
          int indexes[] = { 0, 1, 2, 3, 4, 5 };
      
          int numbers_size = 6;
      
          int largest[] = { -1, -1, -1, -1, -1, -1 };
          int largest_index = 0;
      
          int i;
      
          for (i = 0; i < 6; i++)
          {
              int j;
              int max_index = -1;
              int max = -2147483648;
      
              for (j = 0; j < numbers_size; j++)
              {
                  if (numbers[j] >= max && contains(largest, numbers_size, j) == FALSE)
                  {
                      max_index = j;
                      max = numbers[max_index];
                  }
              }
      
              largest[largest_index++] = max_index;
          }
      
          for (i = 0; i < 6; ++i)
          {
              printf("%d->%d\n", largest[i], numbers[largest[i]]);
          }
      
          return 0;
      }
      

      【讨论】:

      • 我明白了,但我们可以不排序吗?
      • 您可以对数组进行六次迭代,每次记录其索引不在记录数字列表中的最大数字。稍后我可能会使用示例代码编辑此答案。
      【解决方案6】:

      您可能应该使用冒泡排序(并保留一个保存所有原始索引的函数),然后让它显示两个数组的前 6 个数字(来自索引数组和您自己排序的数组)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-08
        • 2020-07-17
        • 2021-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-16
        • 1970-01-01
        相关资源
        最近更新 更多