【问题标题】:What is the number of comparisons required to search an element in a sorted linked list in the worst case?在最坏的情况下搜索排序链表中的元素所需的比较次数是多少?
【发布时间】:2016-06-07 17:48:10
【问题描述】:

这是我大学的数据结构和算法课程测验中的一个问题

在最坏的情况下搜索排序链表中的元素所需的比较次数是多少?

这些是选项:

一个。细胞(n/2)

b. ceil (log n)

c。 n2

d。 ceil ((log n) + 1)

e。 n

根据答案键正确答案是n。

但我认为这样,在排序的链表中,搜索不需要遍历所有元素。它可以从当前跳转到第二个节点(如curr->next->next,并保留前一个指针,如prev = curr->next)并查看该节点的键是否小于要搜索的键,

如果要搜索的键大于当前节点的键,我们重复这个。

否则,我们将搜索键与prev->key 进行比较,如果它们相等,则找到该元素或者它不存在于链表中

这种方法将花费大约 (n/2) 次比较(在与之前比较的情况下 + 1)...所以答案应该是 ceil(n/2) 对吗?我说的对吗?

编辑:这是我上面提到的算法的c版本(链表的头部和要搜索的键是参数。skey是要搜索的键)

void search (struct node * head, int skey)
{
    struct node * curr = head,*prev = NULL;
    
    
    while(1)
    {
        if(curr==NULL)
        {
            if(prev!=NULL)
            {
                if(prev->key== skey)
                {
                    printf("FOUND");
                    break;
                }
                else
                {
                    printf("NOT FOUND");
                    break;
                }
            }
            else
            {
                printf("NOT FOUND");
                break;
            }
        }
        if(curr->key==skey)
        {
            printf("FOUND");
            break;
        }
        else if (curr->key < skey)
        {
            if(curr->next!=NULL)
            {
                prev=curr->next;
                curr=curr->next->next;
                
            }
            else
            {
                printf("NOT FOUND");
                break;
            }
        }
        else
        {
            if(prev!=NULL)
            {
                if(prev->key== skey)
                {
                    printf("FOUND");
                    break;
                }
                else
                {
                    printf("NOT FOUND");
                    break;
                }
            }
            else
            {
                printf("NOT FOUND");
                break;
            }
        }
        
    }
}

【问题讨论】:

  • 你怎么知道cur-&gt;next-&gt;next存在?
  • 从技术上讲,即使您决定先将链表转移到数组中,然后对该数组进行二分搜索,您仍然是正确的“de jure”,因此得出的结论是,您只需要 O(log(n)) comparisons 即可找到密钥。在某些时候,我认为您必须接受“这不是问题所要求的”的概念。
  • 这看起来很奇怪。 @Dolda2000 可以执行二进制搜索是正确的,因为它已经排序......我无法想象为什么它会是 n.
  • @Dolda2000 受到您横向思维的启发。您实际上可以在没有数组的情况下进行二进制搜索。只需遍历 到列表的中间并比较 那个值。然后根据排序顺序重复目标值所在的列表的一半。从技术上讲,遍历期间不会对值进行比较:-)
  • @Mat 当然是这样,但似乎问题必须是对节点内容的比较。如果 next!=null 算作比较,那么答案将大于 $n$。

标签: c algorithm sorting search linked-list


【解决方案1】:

这是一种单步遍历链表的方法,每个节点只有 2 次比较。

while( curr = head; curr != NULL && curr->skey != skey; curr = curr->next);

最坏的情况是skey不在链表中

【讨论】:

    【解决方案2】:

    这在很大程度上取决于搜索的实现方式。

    例子:

    • 执行得很差的搜索可能会检查/比较同一个条目 20 次,然后再移动到下一个条目。

    • 您可以实施二分搜索并减少最坏情况的比较次数(同时增加执行current = current-&gt;next;current = current-&gt;previous; 的次数并使性能变差)。

    • 您可以跟踪“中间条目”;并将最坏情况的比较次数“几乎减半”。

    • 您可以有一个额外的数组来跟踪开始搜索的最佳位置(例如,您要搜索的内容的第一个字符用作该额外数组的索引),并减少数量这样比较。这包括在搜索之前立即构建数组(因为您可以在不进行比较的情况下构建数组)。

    • 如果“您比较的东西”足够小(例如,您正在搜索一个介于 1 和 10 之间的数字的条目),您可以将链表转换为数组,然后使用数组查找;并且有零比较。

    对于最明显的方法(线性搜索),并且仅对于最明显的方法,最坏的情况是您检查了所有条目但没有找到您要查找的内容;这是“每个条目一个比较”或N comparisons

    【讨论】:

      猜你喜欢
      • 2015-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 2016-12-05
      相关资源
      最近更新 更多