我很好奇,因为我最近看到在Java中使用Hashmaps,并想知道Delphi的Sorted String列表是否完全相似。
TStringList对象是否生成Hash以用作每个项目的索引?如何通过Find函数对字符串列表检查搜索字符串?
我经常使用Sorted TStringLists,我只想了解更多内容。
请假设我不知道哈希映射是如何工作的,因为我没有:)
由于
答案 0 :(得分:5)
我通常将这个问题解释为对列表和词典概述的请求。
为了便于论证,我们可以调用我们的列表L
和我们的词典D
。
列表具有真正的随机访问权限。如果您知道其索引,则可以在固定时间内查找项目。字典不是这种情况,它们通常采用基于散列的算法来实现有效的随机访问。
当您尝试查找值时,排序列表可以执行二进制搜索。查找值V是获取索引I的行为,L[I]=V
。二进制搜索非常有效。如果列表未排序,那么它必须执行线性搜索,效率低得多。排序列表可以使用插入排序来维护列表的顺序 - 添加新项目时,它会插入到正确的位置。
您可以将字典视为<Key,Value>
对的列表。您可以迭代所有对,但更常见的是使用索引表示法来查找给定键的值:D[Key]
。请注意,这与在列表中查找值的操作不同 - 当您知道索引I时,它与读取L[I]
类似。
在旧版本的Delphi中,通常会从字符串列表中哄骗字典行为。表现很糟糕。内容的灵活性很小。
使用现代Delphi,有TDictionary
,一个可以容纳任何东西的泛型类。该实现使用哈希,虽然我没有亲自测试其性能,但我理解它是可敬的。
有一些常用的算法可以最佳地使用所有这些容器:未排序列表,排序列表,词典。您只需要使用正确的问题来解决当前的问题。
答案 1 :(得分:4)
TStringList保存数组中的字符串。
如果在未分类(Sorted property = false)字符串列表上调用Sort,则会执行QuickSort以对项目进行排序。
如果将Sorted设置为true,也会发生同样的情况。
如果在未排序的字符串列表上调用Find(或调用find的IndexOf)(Sorted属性= false,即使您明确调用Sort,如果Sorted属性不为true,则列表被视为未排序),则线性搜索是执行比较从开始到匹配的所有字符串。
如果在排序字符串列表上调用查找(Sorted property = true),则执行二进制搜索(有关详细信息,请参阅http://en.wikipedia.org/wiki/Binary_search)。
如果将字符串添加到已排序的字符串列表,则会执行二进制搜索以确定正确的插入位置,数组中的所有后续元素都会移动1并插入新字符串。
由于此插入性能变得越来越差,字符串列表越大。如果要将大量条目插入到已排序的字符串列表中,通常最好关闭排序,插入字符串,然后将Sorted设置为true,以执行快速排序。
这种方法的缺点是你无法阻止重复插入。
编辑:如果你想要一个哈希映射,请使用单位Generics.Collections
中的TDictionary答案 2 :(得分:1)
您可以查看源代码,因为Delphi附带了源代码。按住Ctrl键并单击代码中的“排序”调用。
这是非Unicode Delphi中的简单字母排序,以及稍后版本中稍微复杂的Unicode。您可以为自定义排序顺序提供自己的比较。不幸的是我没有最新版本的Delphi,所以无法确认,但我希望在引擎盖下有一个正确的Unicode感知和区域设置感知字符串比较例程。 Unicode排序/字符串比较并不简单,一点点网络搜索就会指出一些陷阱。
当您在字符串或附加到它们的对象(Objects属性)中分隔文本时,通常会提供自己的比较例程。在这些情况下,您经常要按对象的属性或字符串中第一个字段以外的其他内容进行排序。或者它可能就像想要对字符串进行数字排序一样简单(所以“2”在“1”之后而不是在“19”之后)
答案 3 :(得分:1)
还有一个THashedStringList,可以选择(特别是在较旧的Delphi版本中)。
答案 4 :(得分:0)
答案 5 :(得分:0)
Delphi的字典类型(在启用泛型的Delphi版本中)是与Delphi一起提供的最接近散列图的东西。 THashedStringList使查找速度快于排序字符串列表中的查找速度。你可以在排序的字符串列表中使用二进制搜索进行查找,因此它比强力搜索更快,但速度不如哈希。
散列的一般理论是它是无序的,但在查找和插入时非常快。排序列表在插入时相当快,直到列表的大小变大,尽管它不如插入字典那么有效。
列表的一大好处是它是有序的,但哈希查找字典不是。