C#怎么使用符号表实现查找算法
C#怎么使用符号表实现查找算法
今天小编给大家分享一下C#怎么使用符号表实现查找算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
高效检索海量信息(经典查找算法)是现代信息世界的基础设施。我们使用符号表描述一张抽象的表格,将信息(值)存储在其中,然后按照指定的键来搜索并获取这些信息。键和值的具体意义取决于不同的应用。符号表中可能会保存很多键和很多信息,因此实现一张高效的符号表是很重要的任务。
符号表有时被称为字典,有时被称为索引。
1.符号表
符号表是一种存储键值对的数据结构,支持两种操作:插入(put),即将一组新的键值对存入表中;查找(get),即根据给定的键得到相应的值。符号表最主要的目的就是将一个健和一个值联系起来。
构造符号表的方法有很多,它们不光能够高效地插入和查找,还可以进行其他几种方便的操作。要实现符号表,首先要定义其背后的数据结构,并指明创建并操作这种数据结构以实现插入,查找等操作所需的算法。
API
publicinterfaceISymbolTables
基本实现:
///
2.有序符号表
典型的应用程序中,键都是IComparable 对象,因此可以使用 a.CompareTo( b ) 来比较 a 和 b 两个键。符号表保持键的有序性,可以扩展它的API,根据键的相对位置定义更多实用操作。例如,最大和最小的键。
排名(Rank 方法)和选择 (Select 方法)
检查一个新的键是否插入合适位置的基本操作是排名(Rank,找出小于指定键的键的数量)和选择(Select,找出排名为 k 的键)。对于 0 到 Size()-1 的所有 i 都有 i == Rank( Select(i) ),且所有的键都满足 key == Select( Rank( key ) ) 。
键的等价性
IComparable 类型中 CompareTo 和 Equals 方法是一致的,但为了避免任何潜在的二义性,这里只是用a.CompareTo( b ) == 0 来判断 a 和 b 是否相等。
成本模型
查找的成本模型:在符号表的实现中,将比较的次数作为成本模型。在内循环不进行比较的情况下,使用数组的访问次数。
符号表实现的重点在于其中使用的数据结构和 Get() , Put() 方法。
3.无序链表中的顺序查找
符号表中使用的数据结构的一个简单选择是链表,每个结点存储一个键值对。
Get 方法的实现即为遍历链表,用Equals 方法比较需要查找的键和每个结点中键。如果匹配就返回相应的值,否则返回 null。Put 方法的实现也是遍历,如果匹配就更新相应的值,否则就用给定的键值对创建一个新的结点并将其插入链表的开头。这种方法称为顺序查找。
///
这里我们使用一个字符串数组来测试上面的算法,键是数组中的值,值是插入的索引:
string[]strs=newstring[]{"S","E","A","R","C","H","E","X","A","M","P","L","E"};
下面是顺序查找的索引用例的轨迹:
分析符号表算法比排序算法更困难,因为不同的用例所进行的操作序列各不相同。常见的情形是虽然查找和插入的使用模式是不可预测的,但它们的使用肯定不是随机的。因此我们主要研究最坏情况下的性能。我们使用命中表示一次成功的查找,未命中表示一次失败的查找。
在含有 N 对键值的基于链表的符号表中,未命中的查找和插入操作都需要 N 次比较。命中的查找在最坏情况下需要 N 次比较。特别地,向一个空表中插入 N 个不同的键需要 ~ N^2 /2 次比较。
查找一个已经存在的键并不需要线性级别的时间。一种度量方法是查找表中的每个键,并将总时间除以 N 。在查找表中每个键的可能性都相同的情况下,这个结果就是一次查找平均所需的比较次数。称它为随机命中。由上面的算法可以得到平均比较次数为 ~N/2: 查找第一个键需要比较一次,查找第二个键需要比较两次 ...... 平均比较次数为(1+2+3.....+N)/ N = (N+1)/2。
这证明基于链表的实现以及顺序查找是低效的。
4.有序数组中的二分查找
有序符号表API的实现使用的数据结构是一对平行的数组,一个存储键一个存储值。下面的代码保证数组中IComparable 类型的键有序,然后使用数组的索引来高效地实现 Get 和其他操作。
下面算法的核心是 Rank 方法(它使用二分查找的算法),它返回表中小于给定键的键的数量。对于 Get 方法,只要给定的键存在于表中就返回,否则返回空。
Put 方法,只要给定的键存在于表中,Rank 方法就能够精确告诉我们它的为并去更新,以及当键不存在时我们也能直到将键存储到什么位置。插入键值对时,将更大的键和值向后移一格,并将给定的键值对分别插入到数组。
publicclassBinarySearchST
下面是该算法的用例移动轨迹:
对二分查找的分析
Rank 方法的递归实现使用了二分查找,二分查找比顺序查找快很多。在 N 个键的有序数组中进行二分查找最多需要 (lgN + 1)次比较。
尽管该算法能够保证查找所需的时间是对数级别的,但 Put 方法还是太慢,需要移动数组。对于随机数组,构造一个基于有序数组的符号表所需访问数组的次数是数组长度的平方级别。
向大小为 N 的有序数组中插入一个新的键值对在最坏情况下需要访问 ~2N 次数组,因此向一个空符号表中插入 N 个元素在最坏情况下需要访问 ~N^2 次数组。
对于一个静态表(不允许插入)来说,将其在初始化时就排序是值得的。下面是符号表简单实现的总结:
算法 | 最坏情况下的成本 (N 次插入后) | 平均情况下的成本 (N 次随机插入后) | 是否支持有序性相关的操作 | ||
查找 | 插入 | 查找 | 插入 | ||
顺序查找(无序链表) | N | N | N/2 | N | 否 |
二分查找(有序数组) | lgN | 2N | lgN | N | 是 |
以上就是“C#怎么使用符号表实现查找算法”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注恰卡编程网行业资讯频道。
推荐阅读
-
polyfills怎么按需加载
polyfills怎么按需加载本篇内容主要讲解“polyfills...
-
C#数据类型怎么实现背包、队列和栈
C#数据类型怎么实现背包、队列和栈本文小编为大家详细介绍“C#数据...
-
C#怎么实现冒泡排序和插入排序算法
C#怎么实现冒泡排序和插入排序算法这篇文章主要讲解了“C#怎么实现...
-
C#如何实现希尔排序
C#如何实现希尔排序本篇内容主要讲解“C#如何实现希尔排序”,感兴...
-
C#如何实现归并排序
C#如何实现归并排序这篇文章主要介绍“C#如何实现归并排序”的相关...
-
C#类的静态成员怎么用
C#类的静态成员怎么用这篇“C#类的静态成员怎么用”文章的知识点大...
-
C#的静态函数怎么用
C#的静态函数怎么用这篇文章主要讲解了“C#的静态函数怎么用”,文...
-
C#中的析构函数怎么用
C#中的析构函数怎么用这篇文章主要讲解了“C#中的析构函数怎么用”...
-
怎么用CZGL.ProcessMetrics监控.NET应用
怎么用CZGL.ProcessMetrics监控.NET应用这篇文...
-
C#处理类型和二进制数据转换并提高程序性能的方法
C#处理类型和二进制数据转换并提高程序性能的方法这篇“C#处理类型...