符号表是一种存储键值对的数据结构,支持两种操作插入和 查找,就是 将一组新的键值对存入表中然后 根据给定的键得到对应的值,在编程语言中常用Dictionary原理类似。符号表是一种典型的抽象数据结构,在生活之中应用的场景也很多,可以根据钥匙开门,域名解析的时候的IP地址查询,字典和图书的简介和页数,key和value是密不可分的,通过key我们可以很快找到我们需要的value。
主要通过Node节点存储数据,之前的博客中有关于链表的实现,详情可参考之前的博客,代码有注释就解释太多了,代码如下:
@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的实现:
@implementation BaseNode -(void)setUpData:(NSString *)key value:(NSString *)value next:(BaseNode *)next{ self.key=key; self.value=value; self.next=next; } @end
顺序查找类中的代码:
@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
具体调用:
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 ),代码如下:
@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
实现代码如下:
@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
测试代码:
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);
效果: