【问题标题】:Create a Function which will tell us if an array is sorted or not in C programming创建一个函数,它将告诉我们在 C 编程中数组是否已排序
【发布时间】:2021-09-30 22:17:24
【问题描述】:

C 编程新手^^

我正在处理一项任务,我必须创建一个函数来验证我的数组是否已排序。我必须使用预定义的代码模板并以某种方式解决它。

说明

让我们创建一个函数来告诉我们数组是否已排序。什么是排序的? :-)

编写一个将整数数组作为参数(输入)并返回布尔值(真/假)的函数。

如果整数数组按 ASC(升序)或 DESC(降序)排序,您的函数应该返回 true。 如果整数数组未排序,您的函数应返回 false。

数字将从 -2_000_000 到 2_000_000 数组可能有重复。

我必须用它来解决我的问题

#ifndef STRUCT_INTEGER_ARRAY
#define STRUCT_INTEGER_ARRAY
typedef struct s_integer_array
{
    int size;
    int* array;
} integer_array;
#endif


bool my_is_sort(integer_array* param_1)
{

}

The inputs that will be used to verify my code:

Exemple 0: 

Input: [1, 1, 2]
Output: 
Return Value: true 

Exemple 1: 
Input: [2, 1, -1]
Output: 
Return Value: true 

Exemple 2: 
Input: [4, 7, 0, 3]
Output: 
Return Value: false 

Exemple 3: 
Input: []
Output: 
Return Value: true 

这是我的代码:

#include <stdbool.h>
#ifndef STRUCT_INTEGER_ARRAY
#define STRUCT_INTEGER_ARRAY
typedef struct s_integer_array
{
    int size;
    int* array;
} integer_array;
#endif


bool my_is_sort(integer_array* a)
{
    if (a->size == 1 || a-> size == 0)
    {
        return true;
    }

    int i;
    for (i=0;i<a->size;i++)
    {   //ascending order
        if (a->array[i] <= a->array[i+1]){
            return true;
        }else if (a->array[i] >= a->array[i+1]){
            return true;
        } else {
        return false;
    } 
    }
}

验证代码的输出The output failure i get

我的错误在于输入 -> 输入:[4, 7, 0, 3] 我的代码在应该返回 false 时返回 true。 它返回 true 因为前两个索引 4 小于 7 所以我的代码假定它是按升序排列的,但我不希望我的代码在返回布尔值之前继续循环到下一个。检查 7 之后的数字是否大于 7。但我不知道如何在代码中做到这一点。

谢谢你们!

我知道这对你们很多人来说可能是个愚蠢的问题,但请帮忙。我是新手,我非常喜欢编程。

【问题讨论】:

  • 您总是在循环的第一次迭代中返回。如果你不是,你也会在循环的最后一次迭代中索引数组的末尾,所以你应该在你的 for 循环条件中使用size -1。尝试在循环外添加一个标志变量。当您比较两个值时,它们可以是升序、降序或相等。将当前结果与标志进行比较,如果相反则返回 false。
  • if (a &lt;= b) { ... } else if (a &gt;= b) { ... } else { puts("This line cannot be printed."); }。因为如果a 不是&lt;= b,那么它必须是&gt; b,至少对于整数来说是这样。 (如果比较表达式中的一个或两个都是 NaN,则几乎所有的 NaN 实现中的浮点数可以执行 puts。)加上 @RetiredNinja 所说的。
  • 顺便说明一下:定义数组(或其他)大小的正确类型是来自stddef.hsize_t,而不是int...
  • 两个元素也被排序,所以你可以简单地做if(size &lt;= 2) return true;
  • 提示:找到第一对相等的array[n]array[n+1]并记住这种关系(例如),则返回 false。如果你没有发现这样的不匹配(即循环完成),返回 true。

标签: arrays c sorting pointers structure


【解决方案1】:

这很简单。检查两者升序/降序排序可以一次性完成。

我们通过两个标记变量来做到这一点,一个用于升序[仍然]为真,一个用于降序[仍然]为真。

在循环中,如果当前被比较的元素不相等,则方向之一必须是乱序的。

这是一些重构的代码。有注释:

#include <stdbool.h>

#ifndef STRUCT_INTEGER_ARRAY
#define STRUCT_INTEGER_ARRAY

typedef struct s_integer_array {
    int size;
    int *array;
} integer_array;
#endif

bool
my_is_sort(integer_array *a)
{

    if (a->size <= 1)
        return true;

    int i;

    // true if [still] have ascending sort
    int ascend = 1;

    // true if [still] have descending sort
    int descend = 1;

    // the value of the "previous" array element
    int prev = a->array[0];

    // the value of the "current" array element
    int cur;

    for (i = 1;  i < a->size;  ++i, prev = cur) {
        // early escape -- neither direction is in sort
        if (! (ascend || descend))
            break;

        // get current array value
        cur = a->array[i];

        // compare against previous value
        int dif = cur - prev;

        // elements are the same -- no change in status
        if (dif == 0)
            continue;

        // one of the directions has to be out-of-sort
        if (dif < 0)
            ascend = 0;
        else
            descend = 0;
    }

    return (ascend || descend) ? true : false;
}

更新:

这是一个稍微快一点的版本:

bool
insort_fix1c(integer_array *a)
{
    const int *arr = a->array;
    int size = a->size;

    if (size <= 1)
        return true;

    int i;

    // true if [still] have ascending sort
    int ascend = 1;

    // true if [still] have descending sort
    int descend = 1;

    // the value of the "previous" array element
    int prev = arr[0];

    // the value of the "current" array element
    int cur;

    for (i = 1;  i < size;  ++i, prev = cur) {
        // get current array value
        cur = arr[i];

        // compare against previous value
        int dif = cur - prev;

        // elements are the same -- no change in status
        if (dif == 0)
            continue;

        // one of the directions has to be out-of-sort
        if (dif < 0)
            ascend = 0;
        else
            descend = 0;

        // early escape -- neither direction is in sort
        if ((ascend | descend) == 0)
            break;
    }

    return (ascend | descend) ? true : false;
}

【讨论】:

    【解决方案2】:

    此函数将检查数组是否已排序。

    #ifndef STRUCT_INTEGER_ARRAY
    #define STRUCT_INTEGER_ARRAY
    typedef struct s_integer_array
    {
        int size;
        int* array;
    } integer_array;
    #endif
    
    typedef enum
    {
        des,
        notdetermined;
        asc;
    }SORT_TYPE;
    
    
    bool my_is_sort(integer_array* a)
    {
        bool result = true;
        SORT_TYPE sort = notdetermined; 
        if (a && a -> array && a -> size > 2)
        {
            for(int i = 0; i < a -> size - 1 && result; i++)
            {
                switch(sort)
                {
                    case notdetermined:
                        if(a -> array[i] > a -> array[i + 1]) sort = des;
                        else if(a -> array[i] < a -> array[i + 1])) sort = asc;
                        break;
                    case asc:
                        if(a -> array[i] > a -> array[i + 1])) result = false;
                        break;
                    case des:
                        if(a -> array[i] < a -> array[i + 1])) result = false;
                        break;
                }
            }
        }
        return result;
    }
    

    https://godbolt.org/z/xnM7MYz6b

    【讨论】:

      【解决方案3】:

      这就是我将如何处理这样的事情。它与您被要求的内容有些不同且更复杂,但我希望您可以将这个概念适应您的代码并完成您的任务。

      问题中代码的问题在于,它仅在比较给定数组中的前两个值后返回。相反,它需要比较足够多的值来确定值不相等的第一个比较是升序还是降序,然后继续进行,直到比较违反该规则或到达数组末尾。

      为此,我使用了一个标志变量来跟踪以前的比较。如果任何比较与先前的结果相反,则数组未排序。如果到达终点但没有找到对面,则对数组进行排序。

      我为此使用了enum,但值为 0 表示未确定、-1 表示降序、1 表示升序(或您喜欢的任何其他 3 个值)的 int 也可以正常工作。

      希望这可以帮助您完成作业。祝你好运!

      #include <stdio.h>
      
      typedef enum
      {
          sortUnknown = 0,
          sortAscending,
          sortDescending,
          sortUnsorted
      } SortType;
      
      const char *sortNames[] =
      {
          "   Unknown",
          " Ascending",
          "Descending",
          "  Unsorted",
      };
      
      SortType is_sorted(int* arr, int size)
      {
          if (size <= 1)
          {
              return sortUnknown;
          }
      
          SortType overallSortType = sortUnknown;
          for (int i = 0; i < size - 1; ++i)
          {
              if (arr[i] < arr[i + 1])
              {
                  if (overallSortType == sortDescending)
                  {
                      return sortUnsorted;
                  }
                  overallSortType = sortAscending;
              }
              else if (arr[i] > arr[i + 1])
              {
                  if (overallSortType == sortAscending)
                  {
                      return sortUnsorted;
                  }
                  overallSortType = sortDescending;
              }
          }
          return overallSortType;
      }
      
      void print(int *arr, int size, SortType st)
      {
          printf("%s : ", sortNames[st]);
          for (int i = 0; i < size; ++i)
          {
              printf("%d ", arr[i]);
          }
          printf("\n");
      }
      
      int main()
      {
          int arr1[] = { 1, 1, 2 };
          SortType st = is_sorted(arr1, 3);
          print(arr1, 3, st);
      
          int arr2[] = { 2, 1, -1 };
          st = is_sorted(arr2, 3);
          print(arr2, 3, st);
      
          int arr3[] = { 4, 7, 0, 3 };
          st = is_sorted(arr3, 4);
          print(arr3, 4, st);
      
          int arr4[] = { 3 };
          st = is_sorted(arr4, 1);
          print(arr4, 1, st);
      
          int arr5[] = { 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8, 9 };
          st = is_sorted(arr5, 17);
          print(arr5, 17, st);
      
          return 0;
      }
      

      演示:https://ideone.com/RkfEWI

      输出:

       Ascending : 1 1 2 
      Descending : 2 1 -1 
        Unsorted : 4 7 0 3 
         Unknown : 3 
       Ascending : 1 1 1 1 2 2 2 3 4 5 6 6 6 6 7 8 9 
      

      【讨论】:

        【解决方案4】:

        编写一个以整数数组为参数的函数 (输入)并返回一个布尔值(真/假)。

        这个函数的参数

        bool my_is_sort(integer_array* a)
        

        不接受整数数组。

        在这个for循环中

        int i;
        for (i=0;i<a->size;i++)
        {   //ascending order
            if (a->array[i] <= a->array[i+1]){
                return true;
            }else if (a->array[i] >= a->array[i+1]){
                return true;
            } else {
            return false;
        }
        

        只检查struct s_integer_array 类型对象的数据成员array 指向的数组的前两个元素。由于 for 循环中的 return 语句,不会检查所有其他元素。

        我可以建议下面的演示程序中显示的以下简单的函数实现。

        #include <stdio.h>
        #include <stdbool.h>
        
        bool is_sorted( const int a[], size_t n )
        {
            bool sorted = true;
            
            size_t i = 1;
            
            while ( i < n && a[i-1] == a[i] ) ++i;
            
            if ( i < n )
            {
                if ( a[i-1] < a[i] )
                {
                    while ( ( ++i < n ) && !( a[i] < a[i-1] ) ) { /* empty */ }
                    sorted = i == n;
                }
                else
                {
                    while ( ( ++i < n ) && !( a[i-1] < a[i] ) ) { /* empty */ }
                    sorted = i == n;
                }
            }
            
            return sorted;
        }
        
        int main(void) 
        {
            int a1[] = { 1, 1, 2 };
            size_t n = sizeof( a1 ) / sizeof( *a1 );
            
            for ( size_t i = 0; i < n; i++ )
            {
                printf( "%d ", a1[i] );
            }
            putchar( '\n' );
            
            printf( "The array is sorted is %s\n", is_sorted( a1, n ) ? "true" : "false" );
            putchar( '\n' );
        
            int a2[] = { 2, 1, -1 };
            n = sizeof( a2 ) / sizeof( *a2 );
            
            for ( size_t i = 0; i < n; i++ )
            {
                printf( "%d ", a2[i] );
            }
            putchar( '\n' );
            
            printf( "The array is sorted is %s\n", is_sorted( a2, n ) ? "true" : "false" );
            putchar( '\n' );
        
            int a3[] = { 4, 7, 0, 3 };
            n = sizeof( a3 ) / sizeof( *a3 );
            
            for ( size_t i = 0; i < n; i++ )
            {
                printf( "%d ", a3[i] );
            }
            putchar( '\n' );
            
            printf( "The array is sorted is %s\n", is_sorted( a3, n ) ? "true" : "false" );
            putchar( '\n' );
        
            return 0;
        }
        

        程序输出是

        1 1 2 
        The array is sorted is true
        
        2 1 -1 
        The array is sorted is true
        
        4 7 0 3 
        The array is sorted is false
        

        【讨论】:

        • 我喜欢两个单独的循环方法,因为它的效率很高,但循环条件对我来说看起来很不走运。您不想直接return false; 吗?或者,如果需要单个返回点{ sorted = false; break; }
        • @Aconcagua 在一个简单的函数中使用多个中断或返回是一个坏主意。这是一种糟糕的编程风格。
        • 在我 15 年的专业代码编写中,附加的(隐藏的)if-check 不会通过任何代码审查,但是(依靠编译器来优化是不可取的)。似乎又不是所有人都应用相同的标准......
        猜你喜欢
        • 2021-05-26
        • 2012-05-29
        • 2021-03-23
        • 1970-01-01
        • 1970-01-01
        • 2020-02-23
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        相关资源
        最近更新 更多