算法-符号表的实现(顺序查找和二分查找)
符号表是一种存储键值对的数据结构,支持两种操作插入和查找,就是将一组新的键值对存入表中然后根据给定的键得到对应的值,在编程语言中常用Dictionary原理类似。符号表是一种典型的抽象数据结构,在生活之中应用的场景也很多,可以根据钥匙开门,域名解析的时候的IP地址查询,字典和图书的简介和页数,key和value是密不可分的,通过key我们可以很快找到我们需要的value。
无序链表的顺序查找
主要通过Node节点存储数据,之前的博客中有关于链表的实现,详情可参考之前的博客,代码有注释就不解释太多了,代码如下:
1 2 3 4 5 6 7 8 9 10 11 | @interface BaseNode : NSObject @property (strong, nonatomic ) NSString *key; @property (strong, nonatomic ) NSString *value; @property (strong, nonatomic ) BaseNode *next; -( void )setUpData:( NSString *)key value:( NSString *)value next:(BaseNode *)next; @end |
BaseNode.m的实现:
1 2 3 4 5 6 7 8 9 | @implementation BaseNode -( void )setUpData:( NSString *)key value:( NSString *)value next:(BaseNode *)next{ self .key=key; self .value=value; self .next=next; } @end |
顺序查找类中的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @implementation SequenceTable -( void )put:( NSString *)key value:( NSString *)value{ //遍历节点 for (BaseNode *x= self .first; x!= NULL ; x=x.next) { if ([x.key isEqualToString:key]) { x.value=value; return ; } } //新的节点插在最前面,结构类似栈 BaseNode *tempNode= self .first; self .first=[[BaseNode alloc]init]; [ self .first setUpData:key value:value next:tempNode]; } -( NSString *)get:( NSString *)key{ //遍历数组存在返回值,否则返回null for (BaseNode *node= self .first; node!= NULL ; node=node.next) { if ([key isEqualToString:node.key]) { return node.value; } } return NULL ; } @end |
具体调用:
1 2 3 4 | SequenceTable *table=[[SequenceTable alloc]init]; [table put:@ "FlyElephant" value:@ "http://www.cnblogs.com/xiaofeixiang" ]; [table put:@ "技术交流群" value:@ "228407086" ]; NSLog (@ "技术交流群:%@" ,[table get:@ "技术交流群" ]); |
插入的时候先要查找,查找的时候需要从链表头进行查找,所以插入和查找的平均时间复杂度均为O(n),为了高效我们可以把符号表变成有序的进行二分查找。
有序数组的二分查找
将数组变成有序的我们进行二分查找能够将数组每次比较的次数大大减少,查找的时间复杂度变成O(lgN),插入的时间复杂度变成O(n),代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @interface BinarySearchTable : NSObject @property (strong, nonatomic ) NSMutableArray *keys; @property (strong, nonatomic ) NSMutableArray *values; @property (assign, nonatomic ) NSInteger count; -( void )put:( NSString *)key value:( NSString *)value; -( NSString *)get:( NSString *)key; -( NSInteger )rank:( NSString *)key; @end |
实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | @implementation BinarySearchTable -( NSMutableArray *)keys{ if (!_keys) { _keys=[[ NSMutableArray alloc]initWithCapacity:1]; } return _keys; } -( NSMutableArray *)values{ if (!_values) { _values=[[ NSMutableArray alloc]initWithCapacity:1]; } return _values; } //添加新进入的键值对 -( void )put:( NSString *)key value:( NSString *)value{ NSInteger index=[ self rank:key]; //如果存在键值对,更新值 if (index< self .count&&[ self .keys[index] isEqualToString:key]) { self .values[index]=value; return ; } for ( NSInteger i= self .count; i>index; i--) { self .keys[i]= self .keys[i-1]; self .values[i]= self .values[i-1]; } self .keys[index]=key; self .values[index]=value; self .count= self .count+1; } -( NSString *)get:( NSString *)key{ //查找键,如果存在则返回值,否则返回null NSInteger index=[ self rank:key]; if (index< self .count&&[ self .keys[index] isEqualToString:key]) { return self .values[index]; } return NULL ; } -( NSInteger )rank:( NSString *)key{ //如果存在键则返回该键的位置,可以理解为表中小于它键的数量 NSInteger low=0,high= self .count-1; while (low<=high) { NSInteger mid=low+(high-low)/2; NSInteger diff=[key integerValue]-[ self .keys[mid] integerValue]; if (diff>0) { low=mid+1; } else if (diff<0){ high=mid-1; } else { return mid; } } return low; } @end |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 | SequenceTable *table=[[SequenceTable alloc]init]; [table put:@ "FlyElephant" value:@ "http://www.cnblogs.com/xiaofeixiang" ]; [table put:@ "技术交流群" value:@ "228407086" ]; NSLog (@ "技术交流群:%@" ,[table get:@ "技术交流群" ]); BinarySearchTable *binaryTable=[[BinarySearchTable alloc]init]; [binaryTable put:@ "3" value:@ "FlyElephant" ]; [binaryTable put:@ "9" value:@ "keso" ]; [binaryTable put:@ "10" value:@ "博客园" ]; [binaryTable put:@ "0" value:@ "228407086" ]; NSString *temp=[binaryTable get:@ "3" ]; NSLog (@ "博客园:%@" ,temp); |
效果:
作者:FlyElephant
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述