算法-符号表的实现(顺序查找和二分查找)

 符号表是一种存储键值对的数据结构,支持两种操作插入和查找,就是将一组新的键值对存入表中然后根据给定的键得到对应的值,在编程语言中常用Dictionary原理类似。符号表是一种典型的抽象数据结构,在生活之中应用的场景也很多,可以根据钥匙开门,域名解析的时候的IP地址查询,字典和图书的简介和页数,key和value是密不可分的,通过key我们可以很快找到我们需要的value。

无序链表的顺序查找

主要通过Node节点存储数据,之前的博客中有关于链表的实现,详情可参考之前的博客,代码有注释就不解释太多了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
@interface BaseNode : NSObject
 
@property  (strong,nonatomicNSString  *key;
 
@property  (strong,nonatomicNSString  *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,nonatomicNSMutableArray  *keys;
 
@property  (strong,nonatomic) NSMutableArray  *values;
 
@property  (assign,nonatomicNSInteger  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);

效果:

posted @   Fly_Elephant  阅读(1572)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 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的设计模式综述
点击右上角即可分享
微信分享提示