📜  数据结构概述|设置3(图形,特里,分段树和后缀树)(1)

📅  最后修改于: 2023-12-03 15:10:20.557000             🧑  作者: Mango

数据结构概述|设置3(图形,特里,分段树和后缀树)

本文将介绍四种常用的数据结构:图形、特里、分段树和后缀树。这些结构在计算机科学中得到广泛应用,并且往往能够提高算法的效率。

图形

图形是由一组节点和连接这些节点的边组成的结构。图形可以用来表示很多实际问题,如网络拓扑、路线规划等。图形的基本操作包括遍历、搜索、最短路径、最小生成树等。

在程序中,图形可以用邻接矩阵或邻接表来表示。邻接矩阵是一个二维数组,其中数组元素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)

以上就是四种常用的数据结构:图形、特里、分段树和后缀树的介绍和示例代码。这些数据结构在实际开发中得到广泛应用,熟练掌握它们可以提高算法的效率,让程序更加优秀。