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