数据结构与算法之散列表 链地址法 单链表 / 红黑树升级 实践

数据结构与算法阿木 发布于 4 天前 2 次阅读


摘要:

散列表(Hash Table)是一种基于散列函数将键映射到表中的位置的数据结构,它提供了快速的查找、插入和删除操作。链地址法是解决散列表冲突的一种常用方法,本文将围绕链地址法,分别以单链表和红黑树为基础,探讨其在散列表中的应用与实践。

一、

散列表是一种非常高效的数据结构,广泛应用于各种场景,如数据库索引、缓存、哈希集合等。链地址法是解决散列表冲突的一种方法,通过在每个散列位置维护一个链表来存储具有相同散列值的元素。本文将分别介绍单链表和红黑树在链地址法中的应用,并探讨它们的优缺点。

二、单链表实现链地址法

1. 单链表结构

单链表是一种简单的线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。

python

class ListNode:


def __init__(self, key, value):


self.key = key


self.value = value


self.next = None


2. 散列表实现

使用单链表实现链地址法,需要定义散列表类,并实现插入、查找和删除操作。

python

class HashTable:


def __init__(self, size):


self.size = size


self.table = [None] self.size

def hash(self, key):


return hash(key) % self.size

def insert(self, key, value):


index = self.hash(key)


node = self.table[index]


if node is None:


self.table[index] = ListNode(key, value)


else:


while node.next is not None:


if node.key == key:


node.value = value


return


node = node.next


if node.key == key:


node.value = value


else:


node.next = ListNode(key, value)

def find(self, key):


index = self.hash(key)


node = self.table[index]


while node is not None:


if node.key == key:


return node.value


node = node.next


return None

def delete(self, key):


index = self.hash(key)


node = self.table[index]


prev = None


while node is not None:


if node.key == key:


if prev is None:


self.table[index] = node.next


else:


prev.next = node.next


return


prev = node


node = node.next


3. 优缺点分析

单链表实现链地址法的优点是简单易懂,易于实现。但缺点是查找、插入和删除操作的时间复杂度为O(n),在最坏情况下性能较差。

三、红黑树实现链地址法

1. 红黑树结构

红黑树是一种自平衡的二叉搜索树,它保证了树的高度平衡,从而保证了操作的时间复杂度为O(log n)。

python

class Node:


def __init__(self, key, value, color='red'):


self.key = key


self.value = value


self.color = color


self.left = None


self.right = None


self.parent = None


2. 散列表实现

使用红黑树实现链地址法,需要定义散列表类,并实现插入、查找和删除操作。

python

class HashTable:


def __init__(self, size):


self.size = size


self.table = [None] self.size

def hash(self, key):


return hash(key) % self.size

def insert(self, key, value):


index = self.hash(key)


node = self.table[index]


if node is None:


self.table[index] = Node(key, value)


else:


self._insert(node, key, value)

def _insert(self, node, key, value):


if node.key == key:


node.value = value


return


elif key < node.key:


if node.left is None:


node.left = Node(key, value, 'red')


node.left.parent = node


else:


self._insert(node.left, key, value)


else:


if node.right is None:


node.right = Node(key, value, 'red')


node.right.parent = node


else:


self._insert(node.right, key, value)

def find(self, key):


index = self.hash(key)


node = self.table[index]


while node is not None:


if node.key == key:


return node.value


elif key < node.key:


node = node.left


else:


node = node.right


return None

def delete(self, key):


index = self.hash(key)


node = self.table[index]


if node is not None:


self._delete(node)

def _delete(self, node):


if node.left is None or node.right is None:


temp = node.left if node.left is not None else node.right


if temp is not None:


temp.parent = node.parent


if node.parent is None:


self.table[node.hash] = temp


elif node == node.parent.left:


node.parent.left = temp


else:


node.parent.right = temp


if temp is not None and temp.color == 'red':


return


else:


temp = self._get_min(node.right)


node.key = temp.key


node.value = temp.value


self._delete(temp)

def _get_min(self, node):


while node.left is not None:


node = node.left


return node


3. 优缺点分析

红黑树实现链地址法的优点是查找、插入和删除操作的时间复杂度为O(log n),性能优于单链表。但缺点是实现较为复杂,需要维护红黑树的平衡。

四、总结

本文介绍了散列表的链地址法,分别以单链表和红黑树为基础,探讨了其在散列表中的应用与实践。单链表实现简单易懂,但性能较差;红黑树实现复杂,但性能更优。在实际应用中,可以根据具体需求选择合适的数据结构。

(注:本文代码仅为示例,实际应用中可能需要根据具体情况进行调整。)