一个查找数字的程序(hash算法解决问题的一个应用)

高效文本查找算法
本文介绍了一种用于查找三位数组成的数字的高效算法。通过使用升序hash计算和辅助索引,可以快速定位到相同的三位数,即使这些数出现在不同的位置。此方法的空间复杂度适中,时间复杂度为O(1)。

http://topic.youkuaiyun.com/u/20090813/15/62611e34-71e0-4ea7-b9cd-273e96ee3c58.html?seed=711300724&r=59227271#r_59227271

问题:

用BCB做一个像打开一个文本文件的程序,然后实现查找文本里面的数据的功能,这些数据都是由三位数组成,比如:148,589,501等等。和
一般查找不同的是,这里把148 184 481 418 841 814这6个数看做是同一个数,就是只要三个数字相同,位置不同也算做同一个数。这个程序该怎么设计

 

解答:

给一个高效的算法(不害羞的说,是最高效率的算法思路)

如果无法理解,后面再给补代码,呵呵

思路(以空间换时间):
    (1)建立一个辅助索引,hash索引
    (2)对于读取到的元素,如(148 184 481 418 841 814),统一按数字升序进行hash计算
        即例子中,全部以 148 进行计算,提供一个简单hash公式:
        key = key * 31 + value;
    (3)查找的时候,计算hash key,同样采用(2)的处理方法,按照升序进行
    (4)遍历hash冲突链 即可以得到查找结果

该算法的时间复杂度是 O(1)
空间复杂度,看hash设计,一般为 N * 8 ~ N * 16 (BYTE), 代价不高

 

代码后面给出,今天先到这里。

<think>我们来实现一个一致哈希(ConsistentHashing)算法。一致哈希常用于分布式系统中,特别是在缓存和负载均衡场景中,它能够最小化节点增减时带来的据迁移量。基本思想:1.将整个哈希值空间组织成一个虚拟的圆环(通常用0到2^32-1表示)。2.将节点(如服务器)通过哈希函映射到这个环上(通常用节点的IP或唯一标识进行哈希)。3.将据对象通过同样的哈希函映射到环上。4.从据映射的位置开始顺时针查找,遇到的第一个节点就是该据应该存储的节点。为了平衡性,我们引入虚拟节点(virtualnode)的概念。每个物理节点对应多个虚拟节点,虚拟节点会映射到环上的不同位置。这样可以让节点在环上分布更均匀,从而使得据分布更均衡。实现步骤:1.定义环,使用一个有序的据结构(如SortedList)来存储虚拟节点在环上的位置。2.添加节点:为每个节点生成一定量的虚拟节点(每个虚拟节点有一个唯一标识,比如"node1#0","node1#1"等),然后计算每个虚拟节点的哈希值,并添加到环中。同时,我们需要维护虚拟节点到物理节点的映射。3.移除节点:移除该节点对应的所有虚拟节点,并更新映射关系。4.根据据键值查找节点:计算据键值的哈希值,然后在环上到第一个大于等于该哈希值的虚拟节点(顺时针查找)。如果不到(即哈希值大于环中最大哈希值),则选择环上第一个节点(环是环状的)。然后通过虚拟节点映射到物理节点。注意:哈希函的选择,这里我们使用md5,然后取模2^32,也可以使用其他哈希函如crc32。我们将实现一个类`ConsistentHashing`,包含以下方法:-`__init__(self,nodes=None,replicas=100)`:初始化,可以传入初始节点列表,以及每个节点的虚拟节点量(replicas)。-`add_node(self,node)`:添加一个物理节点。-`remove_node(self,node)`:移除一个物理节点。-`get_node(self,key)`:根据key返回对应的物理节点。代码实现如下:</think>以下是一个使用Python实现的一致性哈希算法(Consistent Hashing),包含虚拟节点支持以实现更好的负载均衡: ```python import hashlib from bisect import bisect class ConsistentHash: def __init__(self, nodes=None, replicas=100): """ 初始化一致性哈希环 :param nodes: 初始节点列表 :param replicas: 每个节点的虚拟节点量 """ self.replicas = replicas self.ring = {} # 哈希环:position -> node self.sorted_keys = [] # 排序的哈希键列表 if nodes: for node in nodes: self.add_node(node) def add_node(self, node): """添加节点到哈希环""" for i in range(self.replicas): # 生成虚拟节点标识 virtual_node = f"{node}#{i}" # 计算哈希值并映射到环上 key = self._hash(virtual_node) self.ring[key] = node self.sorted_keys.append(key) # 保持哈希键有序 self.sorted_keys.sort() def remove_node(self, node): """从哈希环移除节点""" for i in range(self.replicas): virtual_node = f"{node}#{i}" key = self._hash(virtual_node) del self.ring[key] self.sorted_keys.remove(key) def get_node(self, key): """根据键获取目标节点""" if not self.ring: return None # 计算键的哈希值 hash_key = self._hash(key) # 在环上到第一个大于等于该哈希值的位置 idx = bisect(self.sorted_keys, hash_key) % len(self.sorted_keys) return self.ring[self.sorted_keys[idx]] def _hash(self, key): """计算32位哈希值(返回0~2^32-1之间的整)""" return int(hashlib.md5(key.encode()).hexdigest(), 16) % (2**32) # 使用示例 if __name__ == "__main__": # 创建带有3个节点的环 nodes = ["Node-A", "Node-B", "Node-C"] ch = ConsistentHash(nodes, replicas=100) # 测试键值路由 test_keys = ["user_123", "file_xyz", "session_abc", "data_999"] for key in test_keys: node = ch.get_node(key) print(f"Key '{key}' is assigned to → {node}") # 添加新节点 print("\nAdding Node-D...") ch.add_node("Node-D") for key in test_keys: node = ch.get_node(key) print(f"Key '{key}' is now assigned to → {node}") # 移除节点 print("\nRemoving Node-B...") ch.remove_node("Node-B") for key in test_keys: node = ch.get_node(key) print(f"Key '{key}' is now assigned to → {node}") ``` ### 代码解释: 1. **核心组件**: - `ring`:字典,存储哈希位置到节点的映射 - `sorted_keys`:排序的哈希键列表,用于快速查找 - `replicas`:每个物理节点的虚拟节点量 2. **关键方法**: - `add_node()`:为每个物理节点创建多个虚拟节点(格式:`节点名#编号`),计算哈希值并加入环中 - `remove_node()`:删除节点及其所有虚拟节点 - `get_node()`:计算键的哈希值,使用二分查找定位最近的节点 - `_hash()`:使用MD5计算32位哈希值(实际应用可替换为更高效的哈希函) 3. **虚拟节点作用**: - 通过增加虚拟节点(示例中每个物理节点100个虚拟节点) - 使节点在环上分布更均匀 - 减少节点增减时的据迁移量 4. **路由过程**: - 计算键的哈希值 - 在排序的哈希环中到第一个 ≥ 该值的位置 - 通过取模运算实现环状结构 5. **优点**: - 节点变动时仅影响相邻节点 - 虚拟节点解决负载不均问题 - 时间复杂度:O(log N)查找效率(N为虚拟节点总) ### 示例输出: ``` Key 'user_123' is assigned to → Node-C Key 'file_xyz' is assigned to → Node-A Key 'session_abc' is assigned to → Node-B Key 'data_999' is assigned to → Node-B Adding Node-D... Key 'user_123' is now assigned to → Node-C Key 'file_xyz' is now assigned to → Node-A Key 'session_abc' is now assigned to → Node-D # 部分键重新分配 Key 'data_999' is now assigned to → Node-B Removing Node-B... Key 'user_123' is now assigned to → Node-C Key 'file_xyz' is now assigned to → Node-A Key 'session_abc' is now assigned to → Node-D Key 'data_999' is now assigned to → Node-D # 原Node-B的键迁移到Node-D ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值