假设我们有按整数值排序的双向链表:
struct ListItem
{
int value;
ListItem *prev, *next;
};
struct List
{
ListItem *first, *last;
int count;
};
我们可以使用更快的搜索算法(例如二进制搜索)在ListItem
内查找List
以及如何找到?
答案 0 :(得分:4)
对于大多数实际目的,没有。如果您想要更快的搜索,链表是数据结构的不良选择。请考虑使用vector,deque,set或multiset。
编辑:或许最好提供一些关于哪些有意义的指导。如果你有两个基本上分开的阶段,矢量最有意义:要么按顺序插入所有数据,要么插入和排序,然后在数据排序后,数据保持静态,你只需搜索它。 deque几乎是相同的,除了你可以在任何一端插入,所以如果你可能无序地获取数据,但新数据总是属于集合的一端或另一端,它可能是一个不错的选择。
如果您要将插入/删除与查找混合,set
或multiset
效果会更好。它始终保持排序,因此搜索总是相当快。在两者之间(set vs. multiset),选择非常简单:如果您需要确保集合中的每个项目都是唯一的,那么您需要设置。如果您可能有多个具有相同键的项目,则需要多重组合。
答案 1 :(得分:1)
如果节点之间没有基于该值的排序,则不会有其他选择,只能单独检查所有。因此O(n)。
答案 2 :(得分:1)
是的,你可以,但除非“比较值”的操作比“移动指针”昂贵得多,否则完全没有意义。因为通常“移动”与“比较”一样昂贵,而使用普通搜索:
二进制:
在您的示例中,值为“int”,这意味着比较甚至比移动更便宜,因此二进制算法将更加昂贵。
如果您知道列表的大小,二进制可能(可以说)变得更便宜,但是双向逻辑旅行和元素计数的增加的复杂性将会减少价值比较数量减少带来的任何好处。
当然,如果您需要多次搜索,最简单的方法是将链表转换为数组或创建索引 - 指针数组。如果值比int
复杂得多,而且难以比较,当然最需要更快的算法。
答案 3 :(得分:0)
好吧,你仍然需要遍历所有元素直到中间元素。我不确定二进制搜索是否会通过链表加快搜索速度,因为这样。例如,在您的元素位于中间元素之前,逻辑上看起来更快,只是循环遍历这些元素。否则,你只是去中间,看看你的元素与之相关的位置,然后再循环,然后......骑自行车就是真正杀死它的东西。我想这也将取决于你的元素在列表中的确切位置。
答案 4 :(得分:0)
如果您只需要执行几次搜索,我怀疑从头到尾搜索列表将是最佳选择。可能有一些算法可以更有效,但只会稍好一些。
但是,如果您必须多次执行搜索,则将列表复制到支持二进制搜索的有序随机访问容器中将是最佳选择。