您现在的位置是:首页 >其他 >【数据结构】网站首页其他

【数据结构】

MarcoAI 2024-09-14 00:01:02
简介【数据结构】

优缺点

数据结构优点缺点
数组通过索引方便快捷访问元素,适合随机访问。插入和删除操作效率低,大小固定不变。
链表插入和删除操作方便快捷,可以动态调整大小。访问任意元素需要从头查找,效率低。
先进后出,实现简单,可以避免溢出。需要一定的内存空间,不支持随机访问。
队列先进先出,实现简单,可以避免溢出。需要一定的内存空间,不支持随机访问。
可以表示具有层级关系的数据,支持快速搜索、插入、删除操作。需要占用大量内存,平衡树的实现复杂。
可以表示任意复杂的数据关系,支持快速搜索、遍历操作。存储和操作复杂,算法较为复杂。
哈希表插入和搜索操作效率高,不受数据规模影响。空间复杂度高,需要考虑哈希冲突。
可以快速找到最大或最小值,支持动态调整大小。不支持随机访问,删除和插入操作效率较低。
字典树可以高效存储和查找字符串,支持前缀搜索、模式匹配等操作。空间复杂度高,插入和删除操作效率较低。
并查集支持高效的集合操作,可以判断两个元素是否属于同一个集合。实现较为复杂,不支持动态调整大小。

使用场景

数据结构使用场景
数组存储固定大小的数据、排序、随机访问元素等
链表插入和删除操作频繁、需要动态分配内存空间、不需要随机访问元素等
函数调用、表达式求值、处理括号匹配等
队列消息队列、任务队列、层次遍历二叉树、BFS等
数据分类、目录结构、XML/HTML解析等
社交网络、推荐系统、最短路径、拓扑排序、连通性检测等
哈希表数据库索引、缓存、字典等
优先级队列、堆排序、求TOP K等
字典树高效地查找、存储字符串、字符串搜索等
并查集连通分量、图的遍历、非递归的动态连通性问题等

数组

数组是一种线性数据结构,用于存储同一类型的一组数据。它的元素在内存中存储是连续的,可以通过索引快速访问元素,适合随机访问。

下面是一个包含5个元素的整型数组的内存结构示意图:

  Index      0        1      2       3        4
  -----------------------------------------------------
  Element |  10   |  -2   |  3    |  0    |  8    |
  -----------------------------------------------------

链表

链表也是一种线性数据结构,用指针将一组数据按序连接起来,每个节点包含一个数据和一个指向下一个节点的指针。

     +--------+      +--------+      +--------+
head | value  | next | value  | next | value  | None
     +--------+      +--------+      +--------+
        |               |               |
        V               V               V
     +--------+      +--------+      +--------+
     | node 1 |----> | node 2 |----> | node 3 |
     +--------+      +--------+      +--------+

在上面的图中,链表由一个个节点组成,每个节点包含两个部分,一个是 value 表示节点存储的数据,另一个是 next 表示下一个节点的指针。链表的主体是由一个 head 指针指向链表的第一个节点,而最后一个节点的 next 则指向空地址 None。

是一种先进后出的数据结构。

基本操作

  • push:将元素压入栈顶
  • pop:将栈顶元素弹出
  • top:获取栈顶元素但不弹出
  • isEmpty:判断栈是否为空
  • size:获取栈的元素个数

基于数组

class ArrayStack:
    def __init__(self, capacity):
        self._capacity = capacity
        self._data = [None] * self._capacity
        self._size = 0

    def push(self, val):
        if self._size == self._capacity:
            self._expand_capacity()
        self._data[self._size] = val
        self._size += 1

    def _expand_capacity(self):
        self._capacity *= 2
        new_data = [None] * self._capacity
        for i in range(self._size):
            new_data[i] = self._data[i]
        self._data = new_data

    def pop(self):
        if self.is_empty():
            raise Exception("stack is empty")
        self._size -= 1
        return self._data[self._size]

    def is_empty(self):
        return self._size == 0

    def top(self):
        if self.is_empty():
            raise Exception("stack is empty")
        return self._data[self._size - 1]

    def size(self):
        return self._size

基于链表

class StackNode:
    def __init__(self, val):
        self.val = val
        self.next = None


class ChainStack:
    def __init__(self):
        self._top_node = None
        self._size = 0

    def push(self, val):
        new_node = StackNode(val)
        new_node.next = self._top_node
        self._top_node = new_node
        self._size += 1

    def pop(self):
        if self.is_empty():
            raise Exception("stack is empty")
        val = self._top_node.val
        self._top_node = self._top_node.next
        self._size -= 1
        return val

    def is_empty(self):
        return self._top_node is None

    def top(self):
        if self.is_empty():
            raise Exception("stack is empty")
        return self._top_node.val

    def size(self):
        return self._size

队列

队列是一种先进先出的数据结构,类似于排队。

基本操作

  • 入队(enqueue):向队列尾部添加一个新元素。
  • 出队(dequeue):从队列头部删除一个元素。
  • 获取队列头部元素(peek):查看队列头部的元素,但不将其删除。
  • 判断队列是否为空(isEmpty):检查队列是否为空,即队列中是否有元素。
  • 获取队列中元素的数量(size):获取队列中元素的数量。

基于数组

class ArrayQueue:
    def __init__(self, capacity):
        self._capacity = capacity
        self._data = [None] * capacity
        self._head = self._tail = self._size = 0

    def enqueue(self, val):
        if self._size == self._capacity:
            return False
        self._data[self._tail] = val
        self._tail = (self._tail + 1) % self._capacity
        self._size += 1
        return True

    def dequeue(self):
        if self.is_empty():
            return None
        val = self._data[self._head]
        self._head = (self._head + 1) % self._capacity
        self._size -= 1
        return val

    def is_empty(self):
        return self._size == 0

    def size(self):
        return self._size

基于链表

class QueueNode:
    def __init__(self, val):
        self.val = val
        self.next = None


class ChainQueue:
    def __init__(self, capacity):
        self._capacity = capacity
        self._head = self._tail = None
        self._size = 0

    def enqueue(self, val):
        if self._size == self._capacity:
            return False
        node = QueueNode(val)
        if self.is_empty():
            self._head = self._tail = node
        else:
            self._tail.next = node
            self._tail = self._tail.next
        self._size += 1
        return True

    def is_empty(self):
        return self._size == 0

    def dequeue(self):
        if self.is_empty():
            return None
        val = self._head.val
        self._head = self._head.next
        self._size -= 1
        return val

    def size(self):
        return self._size

名词概念

名词概念定义
根节点树的顶层节点,没有父节点
叶节点没有子节点的节点
子节点某个节点连接的下一层节点
父节点某个节点连接的上一层节点
父子关系父节点连接一个或多个子节点,子节点连接一个父节点,它们之间的连结称为父子关系
节点深度从根节点到该节点所经过的边的数量,根节点深度为0
子树以一个节点为根的子树包含该节点及其所有子孙节点,该节点是子树的根节点
树的高度树中节点深度的最大值
节点的度节点子树的数量

特性

  • 一棵非空的树有且只有一个根节点。
  • 每个节点有零个或多个子节点。
  • 每个非根节点有且仅有一个父节点。
  • 如果节点A是节点B的子节点,则B是A的父节点。
  • 如果一棵树的每个节点都不超过n个子节点,则该树称为n叉树。

常用特殊的树

特殊树说明使用场景
二叉树每个节点最多有两个子节点的树算法题、排序、表达式求值等
二叉搜索树一种特殊的二叉树,满足左子节点的值小于根节点,右子节点的值大于根节点搜索、插入和删除操作等
平衡二叉树一种特殊的二叉搜索树,通过旋转节点重新平衡树的高度以防止出现极端情况搜索、排序、实现哈希表等
线段树一种用于处理区间操作的树结构,可以高效地查询和修改区间中的元素动态规划、区间最值查询、区间和查询等
字典树一种特殊的树结构,常用于字符串匹配自动补全、拼写检查、翻译软件等
哈夫曼树一种利用贪心算法构建的树结构,用于压缩数据JPEG、MP3等文件压缩格式
Trie树又称字典树,用于快速检索、查找与匹配字符串快速匹配前缀、查找指定前缀字符串、在大量字符串集合中的查找等
KD树是一种基于二叉树的数据结构,用于高效地处理多维空间中的数据聚类和最近邻搜索等机器学习算法
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。