c – 虽然我们在大O表示法中放下常数,但在现实生活中却是重要的吗?

虽然我了解到big O的符号只是描述了算法的增长率,但我不确定在以下O(n)算法之间现实生活中的效率是否有差异。

要从列表的末尾打印链表中的节点的值k个位置。

给定一个节点:

/* Link list node */
struct node
{
  int data;
  struct node* next;
};

解决方案1 ​​O(n)

该解决方案遍历列表两次,一次查找列表的长度,第二次获取到列表的末尾。

void printNthFromLast(struct node* head, int n)
{
    int len = 0, i;
    struct node *temp = head;


    // 1) Count the number of nodes in Linked List
    while (temp != NULL)
    {
        temp = temp->next;
        len++;
    }

    // Check if value of n is not more than length of the linked list
    if (len < n)
      return;

    temp = head;

    // 2) Get the (n-len+1)th node from the begining
    for (i = 1; i < len-n+1; i++)
    {
       temp = temp->next;
    }
    printf ("%d", temp->data);

    return;
}

解决方案2 O(n)

此解决方案只会遍历列表一次。 ref_ptr指针引导,第二个指针(main_ptr)跟随其后面的k个位置。当ref_ptr到达列表的末尾时,main_ptr应该指向正确的节点(k列表的末尾)。

void printNthFromLast(struct node *head, int n)
{
  struct node *main_ptr = head;
  struct node *ref_ptr = head;

  int count = 0;
  if(head != NULL)
  {
    while( count < n )
     {
        if(ref_ptr == NULL)
        {
           return;
        }
        ref_ptr = ref_ptr->next;
        count++;
     }

     while(ref_ptr != NULL)
     {
        main_ptr = main_ptr->next;
        ref_ptr  = ref_ptr->next;
     }
  }
}

问题是:即使两个解决方案都是O(n),同时留下大的O表示法,第二个解决方案比第一个更长的列表更有效,因为它只会遍历列表一次?

是。在发生相同工作的具体示例中,单个循环可能比循环一组数据两次更有效。但是,O(2n)〜O(n)的思想是2 ns对1 ns可能不重要。 Big O可以更好地展示一段代码如何扩展,例如如果你做出循环O(n ^ 2),则O(n)与O(2n)的差距远小于O(n)vs O(n ^ 2)。

如果您的链表包含数据的数据,那么可能值得减少到单循环迭代。在这种情况下,大O指标可能不足以描述您的最坏情况;您将更好地计时代码并考虑应用程序的需求。

另一个例子是嵌入式软件,其中1 ms与2 ms可能是500 Hz和1 kHz控制回路之间的差异。

获得的教训是它取决于应用程序。

http://stackoverflow.com/questions/35213434/while-we-drop-the-constant-in-big-o-notation-does-it-matter-in-real-life-situat

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 虽然我们在大O表示法中放下常数,但在现实生活中却是重要的吗?