2025数据结构终极指南:从理论到实战的全方位解析

2025数据结构终极指南:从理论到实战的全方位解析

【免费下载链接】notes detailed notes on computer science topics, in one page 【免费下载链接】notes 项目地址: https://gitcode.com/gh_mirrors/notes53/notes

开篇:为什么你需要掌握数据结构?

你是否曾因算法性能瓶颈而彻夜难眠?是否在面试中因无法解释红黑树原理而错失良机?数据结构作为计算机科学的基石,不仅是解决复杂问题的钥匙,更是区分初级与高级开发者的分水岭。本文将带你系统掌握数据结构核心知识,从最基础的链表到复杂的哈希表,从理论原理到实战应用,让你真正理解数据组织的艺术。

读完本文,你将能够:

  • 透彻理解6种核心数据结构的工作原理
  • 掌握不同场景下数据结构的选择策略
  • 手写高质量数据结构实现代码
  • 优化现有系统中的数据存储与访问效率
  • 从容应对技术面试中的数据结构难题

目录

  1. 链表(Linked List):动态数据组织的基石
  2. 堆(Heap):高效优先级管理
  3. 排序数组(Sorted Array):有序数据的经典实现
  4. 二叉搜索树(BST):动态查找的利器
  5. 平衡二叉树(RBT):突破性能瓶颈
  6. 哈希表(Hash Table):常数时间访问的奥秘
  7. 数据结构选型指南:场景与性能对比
  8. 实战案例:从理论到应用
  9. 总结与进阶学习路径

1. 链表(Linked List):动态数据组织的基石

1.1 链表的定义与特性

链表(Linked List)是一种线性数据结构,它与数组的最大区别在于元素不连续存储,而是通过指针(pointer)或引用(reference)连接。这种结构使链表在插入和删除操作上具有天然优势,但随机访问性能较差。

mermaid

核心特性

  • 动态大小:无需预先分配固定内存空间
  • 高效插入/删除:在已知位置操作时为O(1)时间复杂度
  • 随机访问受限:无法像数组那样通过索引直接访问,需从头遍历
  • 额外内存开销:每个节点需要额外空间存储指针

1.2 链表的基本操作

1.2.1 单链表节点定义
public class LinkedList {
    // 内部节点类
    private static class Node {
        int data;       // 节点数据
        Node next;      // 指向下一节点的引用
        
        Node(int data) {
            this.data = data;
            this.next = null;
        }
    }
    
    private Node head;  // 链表头节点
    
    // 构造函数
    public LinkedList() {
        this.head = null;
    }
}
1.2.2 插入操作

头部插入

public void insertAtHead(int data) {
    Node newNode = new Node(data);
    newNode.next = head;  // 新节点指向当前头节点
    head = newNode;       // 更新头节点为新节点
}

尾部插入

public void insertAtTail(int data) {
    Node newNode = new Node(data);
    
    // 如果链表为空,直接将新节点作为头节点
    if (head == null) {
        head = newNode;
        return;
    }
    
    // 遍历到最后一个节点
    Node current = head;
    while (current.next != null) {
        current = current.next;
    }
    
    current.next = newNode;  // 最后一个节点指向新节点
}

指定位置插入

public boolean insertAfter(int target, int data) {
    Node current = head;
    
    // 遍历寻找目标节点
    while (current != null && current.data != target) {
        current = current.next;
    }
    
    // 如果未找到目标节点
    if (current == null) {
        return false;
    }
    
    // 创建新节点并插入
    Node newNode = new Node(data);
    newNode.next = current.next;
    current.next = newNode;
    return true;
}
1.2.3 删除操作
public boolean deleteNode(int key) {
    // 如果链表为空
    if (head == null) {
        return false;
    }
    
    // 如果头节点就是要删除的节点
    if (head.data == key) {
        head = head.next;
        return true;
    }
    
    // 遍历寻找要删除节点的前一个节点
    Node current = head;
    while (current.next != null && current.next.data != key) {
        current = current.next;
    }
    
    // 如果未找到目标节点
    if (current.next == null) {
        return false;
    }
    
    // 删除节点
    current.next = current.next.next;
    return true;
}

1.3 链表的高级变种

1.3.1 双向链表(Doubly Linked List)

mermaid

优势:可以双向遍历,更容易找到前驱节点 劣势:需要额外空间存储前驱指针

1.3.2 循环链表(Circular Linked List)

mermaid

应用场景

  • 实现循环队列
  • 资源分配(如操作系统中的进程调度)
  • 约瑟夫问题(Josephus Problem)求解

1.4 链表的经典问题与解决方案

1.4.1 寻找中间节点

快慢指针法

public Node findMiddleNode() {
    if (head == null) return null;
    
    Node slow = head;  // 慢指针,一次移动1步
    Node fast = head;  // 快指针,一次移动2步
    
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    
    return slow;  // 当快指针到达末尾,慢指针恰在中间
}
1.4.2 判断链表是否有环
public boolean hasCycle() {
    if (head == null) return false;
    
    Node slow = head;
    Node fast = head;
    
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
        
        if (slow == fast) {  // 快慢指针相遇,存在环
            return true;
        }
    }
    
    return false;  // 快指针到达末尾,无环
}
1.4.3 反转链表

迭代法

public void reverse() {
    Node prev = null;
    Node current = head;
    Node next = null;
    
    while (current != null) {
        next = current.next;  // 保存下一个节点
        current.next = prev;  // 反转当前节点的指针
        prev = current;       // 移动prev到当前节点
        current = next;       // 移动current到下一个节点
    }
    
    head = prev;  // 更新头节点
}

递归法

private Node reverseRecursive(Node node) {
    if (node == null || node.next == null) return node;
    
    Node rest = reverseRecursive(node.next);  // 递归反转剩余部分
    node.next.next = node;                    // 将当前节点变为其下一个节点的下一个节点
    node.next = null;                         // 防止循环
    
    return rest;  // 返回新的头节点
}

public void reverseRecursively() {
    head = reverseRecursive(head);
}

2. 堆(Heap):高效优先级管理

2.1 堆的定义与特性

堆(Heap)是一种特殊的完全二叉树(Complete Binary Tree),它满足堆属性(Heap Property):

  • 最小堆(Min-Heap):每个节点的值小于或等于其子节点的值
  • 最大堆(Max-Heap):每个节点的值大于或等于其子节点的值

mermaid 最小堆示例

核心特性

  • 根节点是最小(或最大)元素
  • 是完全二叉树,适合用数组实现
  • 插入和删除操作的时间复杂度为O(log n)
  • 查找最小(或最大)元素的时间复杂度为O(1)

2.2 堆的数组实现

索引关系

  • 对于索引为i的节点:
    • 父节点索引:(i-1)/2(整数除法)
    • 左子节点索引:2i+1
    • 右子节点索引:2i+2
public class MinHeap {
    private int[] heap;
    private int size;
    private int capacity;
    
    public MinHeap(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        this.heap = new int[capacity];
    }
    
    // 获取父节点索引
    private int parent(int i) { return (i - 1) / 2; }
    
    // 获取左子节点索引
    private int leftChild(int i) { return 2 * i + 1; }
    
    // 获取右子节点索引
    private int rightChild(int i) { return 2 * i + 2; }
    
    // 交换两个节点的值
    private void swap(int i, int j) {
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
}

2.3 堆的基本操作

2.3.1 插入操作
public void insert(int key) {
    if (size == capacity) {
        System.out.println("Heap is full");
        return;
    }
    
    // 先将新元素添加到堆的末尾
    int i = size;
    heap[i] = key;
    size++;
    
    // 向上调整(冒泡)以维护堆属性
    while (i != 0 && heap[parent(i)] > heap[i]) {
        swap(i, parent(i));
        i = parent(i);
    }
}
2.3.2 提取最小元素
public int extractMin() {
    if (size <= 0) return Integer.MAX_VALUE;
    if (size == 1) {
        size--;
        return heap[0];
    }
    
    // 存储根节点(最小元素)
    int root = heap[0];
    
    // 将最后一个元素移到根节点位置
    heap[0] = heap[size - 1];
    size--;
    
    // 向下调整以维护堆属性
    minHeapify(0);
    
    return root;
}

// 堆化操作
private void minHeapify(int i) {
    int left = leftChild(i);
    int right = rightChild(i);
    int smallest = i;
    
    if (left < size && heap[left] < heap[i])
        smallest = left;
    if (right < size && heap[right] < heap[smallest])
        smallest = right;
    
    if (smallest != i) {
        swap(i, smallest);
        minHeapify(smallest);  // 递归堆化受影响的子树
    }
}
2.3.3 构建堆
// 从数组构建堆
public void buildHeap(int[] arr) {
    if (arr.length > capacity) {
        System.out.println("Array size exceeds heap capacity");
        return;
    }
    
    size = arr.length;
    heap = Arrays.copyOf(arr, capacity);
    
    // 从最后一个非叶子节点开始堆化
    for (int i = size / 2 - 1; i >= 0; i--) {
        minHeapify(i);
    }
}

2.4 堆的应用

2.4.1 堆排序
public void heapSort(int[] arr) {
    int n = arr.length;
    
    // 构建最大堆
    for (int i = n / 2 - 1; i >= 0; i--) {
        maxHeapify(arr, n, i);
    }
    
    // 逐个提取最大元素
    for (int i = n - 1; i > 0; i--) {
        // 将当前根节点(最大值)移到数组末尾
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        
        // 对剩余元素重新堆化
        maxHeapify(arr, i, 0);
    }
}

// 最大堆堆化操作
private void maxHeapify(int[] arr, int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    
    if (left < n && arr[left] > arr[largest])
        largest = left;
    if (right < n && arr[right] > arr[largest])
        largest = right;
    
    if (largest != i) {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;
        
        maxHeapify(arr, n, largest);
    }
}
2.4.2 优先队列
public class PriorityQueueUsingHeap {
    private MinHeap heap;
    
    public PriorityQueueUsingHeap(int capacity) {
        heap = new MinHeap(capacity);
    }
    
    public void enqueue(int item) {
        heap.insert(item);
    }
    
    public int dequeue() {
        return heap.extractMin();
    }
    
    public int peek() {
        return heap.getMin();
    }
    
    public boolean isEmpty() {
        return heap.size() == 0;
    }
    
    public int size() {
        return heap.size();
    }
}
2.4.3 寻找第K大元素
public int findKthLargest(int[] nums, int k) {
    // 创建一个最小堆
    PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    
    // 将前k个元素加入堆
    for (int i = 0; i < k; i++) {
        minHeap.add(nums[i]);
    }
    
    // 对于剩余元素,如果大于堆顶则替换堆顶
    for (int i = k; i < nums.length; i++) {
        if (nums[i] > minHeap.peek()) {
            minHeap.poll();
            minHeap.add(nums[i]);
        }
    }
    
    // 堆顶元素即为第k大元素
    return minHeap.peek();
}

3. 排序数组(Sorted Array):有序数据的经典实现

3.1 排序数组的特性与优势

排序数组(Sorted Array)是一种元素按特定顺序(通常是升序或降序)排列的线性数据结构。

核心特性

  • 元素按顺序排列
  • 支持随机访问
  • 插入操作可能需要移动大量元素
  • 查找操作可通过二分查找高效进行

优势

  • 查找速度快:可使用二分查找实现O(log n)时间复杂度
  • 有序性:适合需要范围查询的场景
  • 实现简单:无需复杂的指针操作

劣势

  • 插入和删除效率低:平均需要移动O(n)个元素
  • 固定大小:静态数组需要预先确定大小

3.2 排序数组的基本操作

3.2.1 二分查找
// 非递归实现
public int binarySearch(int[] arr, int target) {
    int left = 0;
    int right = arr.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;  // 避免溢出
        
        if (arr[mid] == target) {
            return mid;  // 找到目标,返回索引
        } else if (arr[mid] < target) {
            left = mid + 1;  // 目标在右半部分
        } else {
            right = mid - 1;  // 目标在左半部分
        }
    }
    
    return -1;  // 未找到目标
}

// 递归实现
public int binarySearchRecursive(int[] arr, int target, int left, int right) {
    if (left > right) return -1;
    
    int mid = left + (right - left) / 2;
    
    if (arr[mid] == target) {
        return mid;
    } else if (arr[mid] < target) {
        return binarySearchRecursive(arr, target, mid + 1, right);
    } else {
        return binarySearchRecursive(arr, target, left, mid - 1);
    }
}
3.2.2 插入操作
public int[] insert(int[] arr, int size, int capacity, int element) {
    // 如果数组已满,扩容
    if (size == capacity) {
        capacity *= 2;
        int[] newArr = new int[capacity];
        System.arraycopy(arr, 0, newArr, 0, size);
        arr = newArr;
    }
    
    // 找到插入位置
    int i;
    for (i = size - 1; i >= 0 && arr[i] > element; i--) {
        arr[i + 1] = arr[i];  // 向右移动元素
    }
    
    // 插入新元素
    arr[i + 1] = element;
    size++;
    
    return arr;
}
3.2.3 删除操作
public boolean delete(int[] arr, int size, int target) {
    // 查找目标元素
    int index = binarySearch(arr, target);
    if (index == -1) return false;
    
    // 向左移动元素填补空缺
    for (int i = index; i < size - 1; i++) {
        arr[i] = arr[i + 1];
    }
    
    size--;
    return true;
}

3.3 排序数组的应用场景

3.3.1 范围查询
public List<Integer> rangeQuery(int[] arr, int low, int high) {
    List<Integer> result = new ArrayList<>();
    
    // 找到第一个大于等于low的元素
    int left = 0, right = arr.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] >= low) {
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    int start = left;
    
    // 找到最后一个小于等于high的元素
    left = 0;
    right = arr.length - 1;
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (arr[mid] <= high) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    int end = right;
    
    // 收集结果
    for (int i = start; i <= end; i++) {
        result.add(arr[i]);
    }
    
    return result;
}
3.3.2 频率统计
public Map<Integer, Integer> countFrequency(int[] arr) {
    Map<Integer, Integer> frequencyMap = new HashMap<>();
    
    if (arr == null || arr.length == 0) return frequencyMap;
    
    int current = arr[0];
    int count = 1;
    
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] == current) {
            count++;
        } else {
            frequencyMap.put(current, count);
            current = arr[i];
            count = 1;
        }
    }
    
    // 添加最后一个元素
    frequencyMap.put(current, count);
    
    return frequencyMap;
}

4. 二叉搜索树(BST):动态查找的利器

4.1 BST的定义与特性

二叉搜索树(Binary Search Tree,BST)是一种特殊的二叉树,它满足BST属性

  • 对于任意节点,其左子树中的所有节点值都小于该节点值
  • 对于任意节点,其右子树中的所有节点值都大于该节点值
  • 左子树和右子树也都是二叉搜索树

mermaid 二叉搜索树示例

核心特性

  • 中序遍历(In-order Traversal)可得到有序序列
  • 平均情况下,查找、插入和删除操作的时间复杂度为O(log n)
  • 最坏情况下(退化为链表),时间复杂度为O(n)
  • 无需预先分配固定大小的空间

4.2 BST的节点定义与基本操作

4.2.1 节点定义
public class BSTNode {
    int val;
    BSTNode left;
    BSTNode right;
    
    public BSTNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

public class BinarySearchTree {
    private BSTNode root;
    
    public BinarySearchTree() {
        this.root = null;
    }
}
4.2.2 插入操作
// 递归实现
public BSTNode insertRecursive(BSTNode node, int val) {
    // 如果树为空,创建新节点作为根节点
    if (node == null) {
        return new BSTNode(val);
    }
    
    // 否则递归地向下插入
    if (val < node.val) {
        node.left = insertRecursive(node.left, val);
    } else if (val > node.val) {
        node.right = insertRecursive(node.right, val);
    }
    
    // 返回未改变的节点指针
    return node;
}

public void insert(int val) {
    root = insertRecursive(root, val);
}

// 迭代实现
public void insertIterative(int val) {
    BSTNode newNode = new BSTNode(val);
    
    // 如果树为空,直接将新节点作为根节点
    if (root == null) {
        root = newNode;
        return;
    }
    
    BSTNode current = root;
    BSTNode parent = null;
    
    // 找到插入位置
    while (current != null) {
        parent = current;
        if (val < current.val) {
            current = current.left;
        } else if (val > current.val) {
            current = current.right;
        } else {
            // 值已存在,不插入
            return;
        }
    }
    
    // 插入新节点
    if (val < parent.val) {
        parent.left = newNode;
    } else {
        parent.right = newNode;
    }
}
4.2.3 查找操作
// 递归实现
public boolean searchRecursive(BSTNode node, int val) {
    // 基本情况:树为空或找到值
    if (node == null) return false;
    if (node.val == val) return true;
    
    // 值小于当前节点值,在左子树中查找
    if (val < node.val) {
        return searchRecursive(node.left, val);
    }
    // 否则在右子树中查找
    else {
        return searchRecursive(node.right, val);
    }
}

public boolean search(int val) {
    return searchRecursive(root, val);
}

// 迭代实现
public boolean searchIterative(int val) {
    BSTNode current = root;
    
    // 遍历树直到找到值或到达叶子节点
    while (current != null) {
        if (current.val == val) {
            return true;  // 找到值
        } else if (val < current.val) {
            current = current.left;  // 在左子树中查找
        } else {
            current = current.right;  // 在右子树中查找
        }
    }
    
    return false;  // 未找到值
}
4.2.4 删除操作
// 找到以node为根的树中的最小节点
private BSTNode findMinNode(BSTNode node) {
    BSTNode current = node;
    
    // 循环查找左子节点,直到找到最小节点
    while (current.left != null) {
        current = current.left;
    }
    
    return current;
}

// 递归删除节点
public BSTNode deleteRecursive(BSTNode node, int val) {
    // 基本情况:树为空
    if (node == null) return null;
    
    // 递归查找要删除的节点
    if (val < node.val) {
        node.left = deleteRecursive(node.left, val);
    } else if (val > node.val) {
        node.right = deleteRecursive(node.right, val);
    } else {
        // 找到要删除的节点
        
        // 情况1:叶子节点(没有子节点)
        if (node.left == null && node.right == null) {
            return null;
        }
        // 情况2:只有一个子节点
        else if (node.left == null) {
            return node.right;
        } else if (node.right == null) {
            return node.left;
        }
        // 情况3:有两个子节点
        else {
            // 找到中序后继(右子树中的最小节点)
            BSTNode successor = findMinNode(node.right);
            
            // 用后继节点的值替换当前节点的值
            node.val = successor.val;
            
            // 删除后继节点
            node.right = deleteRecursive(node.right, successor.val);
        }
    }
    
    return node;
}

public void delete(int val) {
    root = deleteRecursive(root, val);
}

4.3 BST的遍历

4.3.1 中序遍历(In-order Traversal)
// 递归实现
public void inorderRecursive(BSTNode node) {
    if (node != null) {
        inorderRecursive(node.left);
        System.out.print(node.val + " ");
        inorderRecursive(node.right);
    }
}

// 迭代实现
public void inorderIterative() {
    Stack<BSTNode> stack = new Stack<>();
    BSTNode current = root;
    
    while (current != null || !stack.isEmpty()) {
        // 遍历到最左节点
        while (current != null) {
            stack.push(current);
            current = current.left;
        }
        
        // current应为null,弹出栈顶元素
        current = stack.pop();
        System.out.print(current.val + " ");
        
        // 访问右子树
        current = current.right;
    }
}
4.3.2 前序遍历(Pre-order Traversal)
// 递归实现
public void preorderRecursive(BSTNode node) {
    if (node != null) {
        System.out.print(node.val + " ");
        preorderRecursive(node.left);
        preorderRecursive(node.right);
    }
}

// 迭代实现
public void preorderIterative() {
    if (root == null) return;
    
    Stack<BSTNode> stack = new Stack<>();
    stack.push(root);
    
    while (!stack.isEmpty()) {
        BSTNode node = stack.pop();
        System.out.print(node.val + " ");
        
        // 先压右子节点,再压左子节点,保证左子节点先被访问
        if (node.right != null) {
            stack.push(node.right);
        }
        if (node.left != null) {
            stack.push(node.left);
        }
    }
}
4.3.3 后序遍历(Post-order Traversal)
// 递归实现
public void postorderRecursive(BSTNode node) {
    if (node != null) {
        postorderRecursive(node.left);
        postorderRecursive(node.right);
        System.out.print(node.val + " ");
    }
}

// 迭代实现
public void postorderIterative() {
    if (root == null) return;
    
    Stack<BSTNode> stack = new Stack<>();
    BSTNode current = root;
    BSTNode lastVisited = null;
    
    while (current != null || !stack.isEmpty()) {
        // 遍历到最左节点
        while (current != null) {
            stack.push(current);
            current = current.left;
        }
        
        BSTNode peekNode = stack.peek();
        
        // 如果右子节点存在且未被访问过,则访问右子树
        if (peekNode.right != null && lastVisited != peekNode.right) {
            current = peekNode.right;
        } else {
            // 否则访问当前节点
            System.out.print(peekNode.val + " ");
            lastVisited = stack.pop();
        }
    }
}

4.4 BST的高级操作

4.4.1 查找最小值和最大值
public int findMin() {
    if (root == null) {
        throw new NoSuchElementException("Tree is empty");
    }
    
    BSTNode current = root;
    while (current.left != null) {
        current = current.left;
    }
    
    return current.val;
}

public int findMax() {
    if (root == null) {
        throw new NoSuchElementException("Tree is empty");
    }
    
    BSTNode current = root;
    while (current.right != null) {
        current = current.right;
    }
    
    return current.val;
}
4.4.2 查找前驱和后继
// 查找前驱(中序遍历中的前一个节点)
public Integer findPredecessor(int val) {
    BSTNode current = root;
    BSTNode predecessor = null;
    
    while (current != null) {
        if (val > current.val) {
            predecessor = current;  // 当前节点可能是前驱
            current = current.right;
        } else if (val < current.val) {
            current = current.left;
        } else {
            // 找到值,寻找其左子树的最大值
            if (current.left != null) {
                BSTNode temp = current.left;
                while (temp.right != null) {
                    temp = temp.right;
                }
                predecessor = temp;
            }
            break;
        }
    }
    
    return (predecessor != null) ? predecessor.val : null;
}

// 查找后继(中序遍历中的后一个节点)
public Integer findSuccessor(int val) {
    BSTNode current = root;
    BSTNode successor = null;
    
    while (current != null) {
        if (val < current.val) {
            successor = current;  // 当前节点可能是后继
            current = current.left;
        } else if (val > current.val) {
            current = current.right;
        } else {
            // 找到值,寻找其右子树的最小值
            if (current.right != null) {
                BSTNode temp = current.right;
                while (temp.left != null) {
                    temp = temp.left;
                }
                successor = temp;
            }
            break;
        }
    }
    
    return (successor != null) ? successor.val : null;
}
4.4.3 计算树的高度
public int height(BSTNode node) {
    if (node == null) {
        return 0;
    }
    
    // 递归计算左右子树的高度
    int leftHeight = height(node.left);
    int rightHeight = height(node.right);
    
    // 返回较高子树的高度加1(当前节点)
    return Math.max(leftHeight, rightHeight) + 1;
}

public int getHeight() {
    return height(root);
}

5. 平衡二叉树(RBT):突破性能瓶颈

5.1 平衡二叉树的必要性

标准二叉搜索树在最坏情况下会退化为链表,导致所有操作的时间复杂度降至O(n)。平衡二叉树通过维护树的高度平衡,确保操作的时间复杂度保持在O(log n)级别。

常见的平衡二叉树类型:

  • AVL树:最早的平衡二叉树,要求左右子树高度差不超过1
  • 红黑树(Red-Black Tree):通过颜色标记和旋转操作维持平衡
  • B树:多路平衡查找树,适合磁盘存储系统
  • B+树:B树的变体,所有叶子节点形成有序链表

5.2 红黑树的定义与特性

红黑树(Red-Black Tree)是一种自平衡二叉搜索树,它通过以下特性确保树的平衡:

  1. 节点颜色:每个节点要么是红色,要么是黑色
  2. 根节点:根节点必须是黑色

【免费下载链接】notes detailed notes on computer science topics, in one page 【免费下载链接】notes 项目地址: https://gitcode.com/gh_mirrors/notes53/notes

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值