📅  最后修改于: 2023-12-03 15:10:20.557000             🧑  作者: Mango
本文将介绍四种常用的数据结构:图形、特里、分段树和后缀树。这些结构在计算机科学中得到广泛应用,并且往往能够提高算法的效率。
图形是由一组节点和连接这些节点的边组成的结构。图形可以用来表示很多实际问题,如网络拓扑、路线规划等。图形的基本操作包括遍历、搜索、最短路径、最小生成树等。
在程序中,图形可以用邻接矩阵或邻接表来表示。邻接矩阵是一个二维数组,其中数组元素A[i][j]等于1表示节点i和j之间有边;如果A[i][j]等于0,则表示节点i和j之间没有边。邻接表则是一个以链表形式存储的数组,其中每个数组元素都表示一个节点,而链表中存储的是与该节点相邻的所有节点。
# 使用邻接矩阵表示图形
graph = [[1, 1, 0, 0], [1, 0, 1, 1], [0, 1, 0, 1], [0, 1, 1, 0]]
# 使用邻接表表示图形
graph = {0: [1, 2], 1: [0, 2, 3], 2: [1, 3], 3: [1, 2]}
特里又称字典树,是一种用于处理字符串的树形数据结构。特里的每个结点代表一个字符串的首字母,而该结点的子结点代表该字符串的下一个字符。
特里可以用于实现字符串的查找、插入和删除。特别地,当特里中所有字符串的长度相同,且没有任何重复前缀时,它就成为了哈希树。
# 特里的节点类
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
# 特里的实现类
class Trie:
def __init__(self):
self.root = TrieNode()
# 插入字符串
def insert(self, word: str) -> None:
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
# 查找字符串
def search(self, word: str) -> bool:
node = self.root
for char in word:
if char not in node.children:
return False
node = node.children[char]
return node.is_end
# 删除字符串
def delete(self, word: str) -> None:
def _delete(node: TrieNode, word: str, index: int) -> bool:
if index == len(word):
node.is_end = False
return len(node.children) == 0
char = word[index]
if char not in node.children:
return False
if _delete(node.children[char], word, index + 1):
del node.children[char]
return len(node.children) == 0
return False
_delete(self.root, word, 0)
分段树是一种用于快速查询区间信息的数据结构。它将整个区间分成若干个小区间,每个小区间计算出一个信息,并将这些信息结合起来得到整个区间的信息。
分段树适用的场景包括区间和、区间最大值、区间最小值等问题。其时间复杂度为O(logn),可以大幅提高这些问题的查询效率。
# 分段树的实现类
class SegmentTree:
def __init__(self, nums: List[int], op: Callable[[int, int], int]):
# 传入的数据列表
self.nums = nums
# 用于合并区间信息的操作函数
self.op = op
# 分段树的节点
self.tree = [None] * (4 * len(nums))
def build(left: int, right: int, index: int):
if left == right:
self.tree[index] = nums[left]
return
mid = (left + right) // 2
build(left, mid, index * 2 + 1)
build(mid + 1, right, index * 2 + 2)
self.tree[index] = self.op(self.tree[index * 2 + 1], self.tree[index * 2 + 2])
build(0, len(nums) - 1, 0)
# 查询区间信息
def query(self, left: int, right: int) -> int:
def _query(left: int, right: int, index: int, node_left: int, node_right: int) -> int:
if left > node_right or right < node_left:
return None
if left <= node_left and right >= node_right:
return self.tree[index]
mid = (node_left + node_right) // 2
left_val = _query(left, right, index * 2 + 1, node_left, mid)
right_val = _query(left, right, index * 2 + 2, mid + 1, node_right)
if left_val is None:
return right_val
elif right_val is None:
return left_val
else:
return self.op(left_val, right_val)
return _query(left, right, 0, 0, len(self.nums) - 1)
后缀树是一种用于处理字符串的树形数据结构。后缀树的构建过程是先构建字符串的所有后缀,再将这些后缀插入到一棵树中。
后缀树可以用于实现字符串查找、最长公共子串、最长回文子串等问题。其时间复杂度也为O(nlogn),可以在很短的时间内处理较大的字符串。
# 后缀树的节点类
class SuffixNode:
def __init__(self, start=0, end=0):
self.children = {}
self.start = start
self.end = end
# 后缀树的实现类
class SuffixTree:
def __init__(self, string: str):
self.string = string
self.root = SuffixNode()
self.end_index = len(string) - 1
def build_suffix_tree(node: SuffixNode, start: int):
for char in node.children:
child = node.children[char]
if child.start <= start <= child.end:
mid = child.start + (start - child.start)
left_child = SuffixNode(child.start, mid - 1)
right_child = SuffixNode(mid, child.end)
node.children[char] = left_child
left_child.children[self.string[mid]] = right_child
right_child.children[self.string[child.end + 1]] = child
build_suffix_tree(right_child, start)
for i in range(len(string)):
node = self.root
for j in range(i, len(string)):
char = string[j]
if char not in node.children:
node.children[char] = SuffixNode(j, self.end_index)
node = node.children[char]
build_suffix_tree(self.root, i)
以上就是四种常用的数据结构:图形、特里、分段树和后缀树的介绍和示例代码。这些数据结构在实际开发中得到广泛应用,熟练掌握它们可以提高算法的效率,让程序更加优秀。