当前位置: 首页 > web >正文

数据结构—(链表,栈,队列,树)

本文章写的比较乱,属于是缝合怪,很多细节没处理,显得粗糙,日后完善,今天赶时间了。

1. 红黑树的修复篇章

2. 红黑树的代码理解(部分写道注释之中了)

3. 队列与栈的代码

4. 重要是理解物理逻辑,从而理解代码逻辑

目录

一 链表

1. 单向链表

2. 双向链表

双向链表的操作(c语言)

1. linked_list_common.h

2. link.c

3. main.c

3. 循环列表

1. 单向循环列表

2. 双向循环列表

4. 静态链表

二 栈(stack)(代码暂不演示)

三 队列(queue) (代码暂不演示)

四 树(tree)

1. 二叉树(Binary Tree)

2. 二叉搜索树(BST)

3. AVL 树

4. B 树

5. 红黑树

1. red_black_common.h

2. red_black_tree.c

3. main.c

4. 总结

1. 左右旋

2. 修复(变色,左右旋转)


一 链表

链表(Linked List) 是一种线性数据结构,由一系列节点(Node)通过指针链接而成。与数组不同,链表的元素在内存中非连续存储,每个节点独立分配内存

类型方向性内存开销适用场景
单向链表单向简单数据管理(如栈、队列)
双向链表双向高(2指针)频繁双向遍历(如浏览器历史记录)
循环链表环状同单向/双向轮询任务、循环缓冲区
静态链表单向/双向固定数组无动态内存环境(如嵌入式开发)
  1. 单向链表

    • 实现栈(LIFO)、队列(FIFO)。

    • 轻量级数据集合管理(如学生成绩表)。

  2. 双向链表

    • 浏览器前进/后退功能。

    • 文本编辑器的撤销/重做操作。

  3. 循环链表

    • 操作系统进程调度(时间片轮转)。

    • 音乐播放器的循环播放列表。

  4. 静态链表

    • 内存受限的嵌入式系统。

    • 预分配固定内存池的实时系统。

(此处重点且详细的说双向列表,双向列表会了之后,其余两个也就差不多了)

1. 单向链表

结构定义

  • 每个节点包含 数据域 和 指向下一个节点的指针

  • C语言结构体

typedef struct SNode {int data;               // 数据域struct SNode *next;     // 指向下一节点的指针
} SNode;

特点:

  • 单向遍历,只能从头节点开始访问后续节点。

  • 插入/删除操作需定位前驱节点。

  • 示例操作

// 在头节点后插入新节点
void insertAtHead(SNode **head, int val) {SNode *newNode = (SNode*)malloc(sizeof(SNode));newNode->data = val;newNode->next = *head;*head = newNode;
}

2. 双向链表

结构定义

  • 每个节点包含 数据域指向前驱节点的指针 和 指向后继节点的指针

  • C语言结构体


typedef struct linked_list_node
{// 节点数据void *data; // 8位// pre节点指针,指向的是前一个节点 8位struct linked_list_node *prev;// next指针指向的是下一个节点 8位struct linked_list_node *next;} node;// 2.定义链表-结构体,此结构点表示的是
typedef struct
{// 头结点node *head;// 尾节点node *tail;// 节点的个数int size;} linked_list;

特点:

  • 支持双向遍历(从头到尾或从尾到头)。

  • 插入/删除操作更高效(可直接访问前驱和后继)。

双向链表的操作(c语言)

包含了前插插入,后插插入,中间插入,删除,查找等等

1. linked_list_common.h
#ifndef LINKED_LIST_COMMON
#define LINKED_LIST_COMMON/*双向链表结构节点表示首节点  前去节点 数据 后区节点*/// 节点声明,数据在次结构体,总体长度为24
typedef struct linked_list_node
{// 节点数据void *data; // 8位// pre节点指针,指向的是前一个节点 8位struct linked_list_node *prev;// next指针指向的是下一个节点 8位struct linked_list_node *next;} node;// 2.定义链表-结构体,此结构点表示的是
typedef struct
{// 头结点node *head;// 尾节点node *tail;// 节点的个数int size;} linked_list;// 3.创建一个节点需要自己开辟空间,即使用上的nide指针的
node *create_node(void *data);// 4.初始化链表
void init_linked_list(linked_list *list);// 中间插入
void insert_after(linked_list *list, node *prev, void *data);// 人为规定当前案例 都放入int类型数据
// 整数int类型比较函数
int compare_int(void *a, void *b);// 添加 prepend 和 append 的声明
void prepend(linked_list *list, void *data);
void append(linked_list *list, void *data);// 在链表中查找特定数据的节点,插入必须先查找对应的节点
node *search_node(linked_list *list, void *data, int (*compare)(void *, void *));// 示例:打印int数据链表的内容
void print_int_linked_list(linked_list *list);// 删除节点,进行三次判断,判断是否为头节点,判断是否为节点,否则就是中间节点,然后写出每个删除的逻辑
// 逻辑结束后,释放所被删除的内存空间
void delete_node(linked_list *linked, node *node);// last.清空链表
void clean_linked_list(linked_list *list);#endif
2. link.c
#include <stdio.h>
#include <stdlib.h>
#include "../inc/linked_list_common1.h"/*在此处定义
*/
// 1.创建一个节点需要自己开辟空间,即使用上的nide指针的
node *create_node(void *data)
{// 创建空间,准备存取数据,别忘记了释放空间// calloc(1, sizeof(node))由于calloc创建的是一个没有类型的类型的数据,需要给强转成相对应的类型嗯node *new_node = (node *)calloc(1, sizeof(node));// 如果内存无法开辟,即没有足够大的空间,会导致开辟失败if (new_node == NULL){printf("内存溢出,创建节点失败\n");exit(EXIT_FAILURE); // 异常退出}// 如果空间可以开辟,则使用结构体指针将其赋初始值new_node->data = data;new_node->prev = NULL;new_node->next = NULL;return new_node;
}// 2.初始化链表,因为暂时没有数据
void init_linked_list(linked_list *list)
{// 头结点list->head = NULL;// 尾节点list->tail = NULL;// 链表的节点个数list->size = 0;
}
// 7.在链表的中间插入节点。三个参数,即为,列表,前驱节点为参数,和数据
void insert_after(linked_list *list, node *prev, void *data)
{// 上一个节点的pre指向上上个数据,next指向下一个数据,要在中间插入一个数据的话,既要改变上一个节点的next,也要改变下一个节点的prev// 即在于找到一个prev即可找到上一个节点的next//  7.1判断要插入的prev的节点是否为null,没有的话,找不到前一个数据,无法插入if (prev == NULL){printf("前驱节点不能为NULL...\n");return; // 结束程序}// 7.2创建新节点 ,此节点就是要被插入的节点,node *new_node = create_node(data);// 7.3 修改新节点的prev和next指针,修改新节点的直接前驱指针,新节点的直接后继指针为 直接前驱的nextnew_node->prev = prev;new_node->next = prev->next;// 7.4 prev为尾节点,更新新节点为新的尾节点if (prev->next == NULL){list->tail = new_node;}else{// prev不是尾节点,更新prev旧的后继节点的prev指针指向新节点prev->next->prev = new_node;}// 设置prev的next指针指向新节点prev->next = new_node;// 链表节点个数+1list->size++;
}// 在链表头部插入数据
void prepend(linked_list *list, void *data)
{node *new_node = create_node(data);if (list->head == NULL){// 如果链表为空,头尾节点都指向新节点list->head = new_node;list->tail = new_node;}else{// 链表非空,更新头节点new_node->next = list->head;list->head->prev = new_node;list->head = new_node;}list->size++;
}// 在链表尾部插入数据
void append(linked_list *list, void *data)
{node *new_node = create_node(data);if (list->tail == NULL){// 如果链表为空,头尾节点都指向新节点list->head = new_node;list->tail = new_node;}else{// 链表非空,更新尾节点new_node->prev = list->tail;list->tail->next = new_node;list->tail = new_node;}list->size++;
}// 人为规定当前案例 都放入int类型数据
// 整数int类型比较函数
int compare_int(void *a, void *b)
{// 比较数值相减是否为0,0则表示相同return *(int *)a - *(int *)b;
}// 在链表中查找特定数据的节点,插入必须先查找对应的节点,容纳后才能执行中间插入操作,
// 即必须要知道前一个节点的位置,即他的prev
node *search_node(linked_list *list, void *data, int (*compare)(void *, void *))
{// 首先必须要从list的head开始遍历,此处名称为迭代,先获取list的head的节点node *current = list->head;// 遍历列表,查找节点while (current != NULL){// 比较函数返回0,表示两个值相等if (compare(current->data, data) == 0){// 返回找到的节点return current;}// 继续比较下一个节点current = current->next;}// 如果循环结束都没有找到数据对应的节点,说明该链表不存在该数据return NULL;
}// 示例:打印int数据链表的内容,全部内容,其作用与查找节点一样
void print_int_linked_list(linked_list *list)
{// 获取头结点node *current = list->head;printf("双向链表内容:\n");// 迭代器遍历while (current != NULL){printf("%d ", *(int *)current->data);// 继续下一个current = current->next;}printf("\n");printf("此时链表总共有%d个节点\n", list->size);
}// 删除节点,此处有带商榷
void delete_node(linked_list *list, node *node)
{// 判断节点不能为空if (node == NULL){printf("节点不能为空\n");return;}// 判断是否为头节点if (node == list->head){ // 如果是头节点,则使其下一个节点的list->head = node->next;if (list->head != NULL){list->head->prev = NULL;}else{// 如果删除后链表为空,更新尾节点list->tail = NULL;printf("本次删除的为头节点%d\n", *(int *)node->data);}}// 判断是否为尾节点else if (node == list->tail){list->tail = node->prev;if (list->tail != NULL){list->tail->next = NULL;}else{// 如果删除后链表为空,更新头节点list->head = NULL;printf("本次删除的为尾节点%d\n", *(int *)node->data);}}// 中间节点else{node->prev->next = node->next;node->next->prev = node->prev;printf("本次删除的为中部节点%d\n", *(int *)node->data);}// 释放节点内存free(node);list->size--;
}// last.清空链表
void clean_linked_list(linked_list *list)
{// 获取头结点,先用上一个节点找到下一个节点,然后删除上一个节点node *current = list->head;// 迭代器  获取节点,释放节点空间 利用迭代循环找到节点释放空间while (current != NULL){// 头结点不为Nullnode *temp = current;// 获取下一个节点current = current->next;// 释放节点的内存空间free(temp);}// 头结点list->head = NULL;// 尾节点list->tail = NULL;// 链表的节点个数list->size = 0;
}
3. main.c
#include <stdio.h>
#include <stdlib.h>
#include "../inc/linked_list_common1.h"int main(int argc, char const *argv[])
{// 1.初始化链表linked_list list; // 声明开辟内存init_linked_list(&list);// 2.在链表头部插入数据int a = 10, b = 20, c = 30;prepend(&list, &a);prepend(&list, &b);prepend(&list, &c);// 打印print_int_linked_list(&list);// 3.在链表尾部插入数据int e = 40, f = 50;append(&list, &e);append(&list, &f);// 打印print_int_linked_list(&list);// 4.在链表中间插入数据// 4.1查找某个节点int g = 60;node *prev = search_node(&list, &c, compare_int);insert_after(&list, prev, &g);// 打印print_int_linked_list(&list);// 删除节点// 查找要删除的节点,node *target_node = search_node(&list, &a, compare_int);if (target_node != NULL){delete_node(&list, target_node);}else{printf("未找到要删除的节点\n");}print_int_linked_list(&list);// last.清空链表clean_linked_list(&list);return 0;
}

3. 循环列表

特点:

  • 无明确的头尾界限,适合循环访问场景(如轮询调度)。

1. 单向循环列表

结构定义

  • 单向循环链表:尾节点的 next 指针指向头节点。

2. 双向循环列表

结构定义

  • 双向循环链表:头节点的 prev 指向尾节点,尾节点的 next 指向头节点。

4. 静态链表

结构定义

  • 使用数组模拟链表,节点通过数组下标链接。

特点:

  • 无需动态内存分配,适用于不支持指针的环境(如嵌入式系统)。

  • 内存固定,无法动态扩展。

二 栈(stack)(代码暂不演示)

定义:后进先出(LIFO)的线性结构,仅允许在栈顶操作。
核心操作

  • push:入栈。

  • pop:出栈。

  • peek:查看栈顶元素。

队列,和栈比较相似,特殊的线性表(执行先进先出,谁头谁尾,有待商榷)

循环队列:

链式队列:数据与 指针域

需要根据结构图来重新模拟一下结构体的创建的理念

首先明白一点,我大概都懂他们的逻辑结构关系,我也知道他们的指针其什么作用


 

1.明白队列的物理结构关系

2.根据物理结构关系来定义结构体(结构体为何有两个,两个分别是什么作用,为和不创建一个)

3.根据物理结构来定义这个数据结构,使用函数写出,让这个链表成为队列,即数据结构在c语言中并不是一种真正的结构,而是人为定义的,因为人类需要使用这种结构,例如现实问题,排队进游乐场等等

三 队列(queue) (代码暂不演示)

定义:先进先出(FIFO)的线性结构,队尾插入,队头删除。
核心操作

  • enqueue:入队。

  • dequeue:出队。

  • front:查看队头元素。

重难点

  • 栈空判断:出栈前必须检查 top 是否为 NULL(否则导致未定义行为)。

  • 内存安全:出栈后必须释放节点内存。

应用场景

  • 函数调用栈(递归实现)。

  • 括号匹配、表达式求值。

结构体:

// 1.定义队列中节点的
typedef struct queue_node
{// 数据域void *data;// 指针域struct queue_node *next;
} node;// 2.定义队列的结构体
typedef struct
{// 对首节点node *front;// 对尾节点node *rear;// 队列中节点的个数int size;
} queue;

四 树(tree)

树(Tree)是一种非线性数据结构,由节点(Node)和边(Edge)组成,满足以下条件:

  • 每个树有且仅有一个根节点(Root)。

  • 除根节点外,每个节点有且仅有一个父节点

  • 从根节点到任意节点有唯一路径。

1. 二叉树(Binary Tree)

  • 定义:每个节点最多有 2 个子节点(左和右)。

  • 特点:结构简单,适合递归操作。

  • 应用:表达式树、哈夫曼编码。

  • C 代码结构

typedef struct TreeNode {int data;struct TreeNode* left;struct TreeNode* right;
} TreeNode;

2. 二叉搜索树(BST)

  • 定义:左子树所有节点值 < 根节点值 < 右子树所有节点值。

  • 特点:中序遍历结果为有序序列。

  • 应用:动态数据排序、字典。

  • 插入代码

TreeNode* insertBST(TreeNode* root, int val) {if (root == NULL) {TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));node->data = val;node->left = node->right = NULL;return node;}if (val < root->data) root->left = insertBST(root->left, val);else root->right = insertBST(root->right, val);return root;
}

3. AVL 树

  • 定义:平衡二叉搜索树,任意节点左右子树高度差 ≤ 1。

  • 特点:通过旋转(左旋/右旋)保持平衡。

  • 应用:数据库索引、实时高频查询。

  • 结构扩展

typedef struct AVLNode {int data;int height;struct AVLNode *left, *right;
} AVLNode;

4. B 树

  • 定义:多路平衡搜索树,每个节点可包含多个键和子节点。

  • 特点:减少磁盘 I/O,适合大规模数据。

  • 应用:文件系统、数据库存储。

5. 红黑树

  • 定义:自平衡二叉搜索树,通过颜色标记和规则保持平衡。

  • 特点:插入/删除效率高,广泛用于库函数(如 C++ STL)。

  • 规则

    1. 节点是红或黑。

    2. 根和叶子(NIL)是黑。

    3. 红节点的子节点必为黑。(即红不能连续)

    4. 任意节点到叶子的路径包含相同数量黑节点。

    1.节点颜色:个节点都是红色或黑色
    2.根节点:根节点必须是黑色
    3.叶子节点:所有的叶子节点(即空节点)都是黑色
    ​4.红色节点的约束:红色节点的子节点必须是黑色(即红色节点不能有红色子节点)。
    5.黑色节点的平衡:从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点


​这些特性确保了红黑树的平衡性,使得其在最坏情况下的时间复杂度仍然保持在 O(logN)。具体来说,红黑树通过以下方式实现自平衡:

1. red_black_common.h
#ifndef RED_BLACK_COMMON_H
#define RED_BLACK_COMMON_H// 使用枚举 定义节点颜色
typedef enum
{RED,BLACK
} node_color;// 定义树,包含根节点,哨兵节,因为根节点与哨兵节点没有继续分支所以,树的结构体只包含两个数据
// 由于普通的节点,还有数据存在,即为令起一个结构体存放
typedef struct red_black_tree_common
{// 根节点tree_node *root_node;// 哨兵节点tree_node *nil_node;} tree;// 定义树的节点,普通树节点分为数据,左右子结点,及其这个节点的父节点(父节点有可能是根节点),节点颜色,
typedef struct tree_node
{// 1.数据域void *data;// 2.节点的颜色node_color color;// 3.父节点struct rb_tree_node *parent;// 4.左子节点struct rb_tree_node *left_child;// 5.右子节点struct rb_tree_node *right_child;
} tree_node;// 4.创建一个新的红黑树节点,新节点默认为红色,左右子节点和父节点都指向哨兵节点
// 定义树,返回值为树节点的指针类型,参数为tree指针,与数据指针
tree_node *create_node(tree *tree, void *data);// 5.初始化一棵空树,根节点为nil,并且哨兵节点颜色为黑色(最下面的叶子节点)
// 创建一个空树,空树只包含根节点与哨兵节点
tree *create_rb_tree();
/*左旋右旋,这层代码还是简单的,我想执导的是左右转的目的是什么,或者说在现实世界的应用情况在什么情况下可以用到左右旋?----在修复的时候用得到,要维护红黑树的平衡及规则左右旋转,先维护x与y的关系,即谁是谁的分支,重新定义x与y的双向关系1.先判断子结点上升的的节点与源节点的子关系,上升节点的分支与源节点的子关系2.判断父关系
(分支节点的的父节点)上升节点的某个分支不为哨兵节点的话,则判断其分支节点的指向为源节点(认爹)y->left_child->parent=x;x与y的关系有三种可能性1.x(源节点)为根节点,判断(x->parent==tree->nil_node),则y就等于根节点,即tree->root_node=y;2.即x不是根节点,判断x是其父节点的那个位置的节点,然后执行x->parent->left_child=y;3.另一个节点一样
*/// last1.释放节点
// 释放树节点的空间
void free_tree(tree *tree, tree_node *node);// last2.释放树
// 释放树的空间
void destroy_tree(tree *tree);#endif
2. red_black_tree.c
#include <stdio.h>
#include <stdlib.h>
#include "../inc/rb_tree_common.h"// 4.创建一个新的红黑树节点,新节点默认为红色,左右子节点和父节点都指向哨兵节点
rb_tree_node *create_node(rb_tree *tree, void *data)
{// 动态分配内存给新节点rb_tree_node *node = (rb_tree_node *)calloc(1, sizeof(rb_tree_node));if (node == NULL){printf("内存溢出,动态分配失败\n");exit(EXIT_FAILURE);}// 设置新节点存储的数据node->data = data;// 新节点的颜色默认为红色node->color = RED;// 左右子节点和父节点都指向哨兵节点node->parent = tree->nil_node;node->left_child = tree->nil_node;node->right_child = tree->nil_node;// 返回创建的节点return node;
}// 5.初始化一棵空树,根节点为nil,并且哨兵节点颜色为黑色(最下面的叶子节点)
rb_tree *create_rb_tree()
{// 动态分配内存给红黑树rb_tree *tree = (rb_tree *)calloc(1, sizeof(rb_tree));if (tree == NULL){printf("内存溢出,动态分配失败\n");exit(EXIT_FAILURE);}// 创建哨兵节点tree->nil_node = (rb_tree_node *)calloc(1, sizeof(rb_tree_node));if (tree->nil_node == NULL){printf("内存溢出,动态分配失败\n");exit(EXIT_FAILURE);}// 哨兵节点默认为黑色tree->nil_node->color = BLACK;// 初始化红黑树,没有插入任何节点// 根节点指向哨兵节点tree->root_node = tree->nil_node;return tree;
}/*
红黑树的插入过程和二叉查找时的插入过程基本类似,不同的地方在于红黑树插入新节点后,需要进行调整,以满足红黑树的性质:1.节点颜色:每个节点都是红色或黑色。2.根节点:根节点必须是黑色。3.叶子节点:所有的叶子节点(即空节点)都是黑色。​4.红色节点的约束:红色节点的子节点必须是黑色(即红色节点不能有红色子节点)。5.黑色节点的平衡:从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。
​这些特性确保了红黑树的平衡性,使得其在最坏情况下的时间复杂度仍然保持在 O(logN)。具体来说,红黑树通过以下方式实现自平衡:旋转操作:包括左旋和右旋,用于调整节点的位置以维持树的平衡。变色操作:用于调整节点的颜色以满足红黑树的特性。
*/
// 6.左旋操作:左旋x,将x节点的右子节点提升为其父节点,并将x下移至其右子节点的左子节点的,左旋用于红黑树失衡调整的结构
void left_rotate(rb_tree *tree, rb_tree_node *x)
{// 6.1设置y为x的右子节点rb_tree_node *y = x->right_child;// 6.2将y的左子树作为x的右子树x->right_child = y->left_child;// 6.3 如果y的左子节点不是哨兵节点,要更改其父节点为xif (y->left_child != tree->nil_node){y->left_child->parent = x;}// 6.4让y的父节点指向x的父节点y->parent = x->parent;// 6.5如果x是根节点,更新y为根节点if (x->parent == tree->nil_node){// 如果x是根节点,则更新根节点为ytree->root_node = y;}else if (x == x->parent->left_child){// x是父节点的左子节点,更新y为其左子节点x->parent->left_child = y;}else{x->parent->right_child = y;}// 6.6设置x为y的左子节点y->left_child = x;// 6.7设置x的父节点为yx->parent = y;
}// 7.右旋操作:右旋y,将y节点的左子节点提升为其父节点,并y下移至其左子节点的右子节点的,右旋用于红黑树失衡调整的结构
void right_rotate(rb_tree *tree, rb_tree_node *y)
{// 7.1设置x为y的左子节点rb_tree_node *x = y->left_child;// 7.2设置x的右子节点为y的左子节点y->left_child = x->right_child;if (x->right_child != tree->nil_node){// 如果x的右子节点不为哨兵节点 ,更新其父节点为yx->right_child->parent = y;}// 7.3让x的父节点指向y的父节点x->parent = y->parent;if (y->parent == tree->nil_node){// 更新x为根节点tree->root_node = x;}else if (y == y->parent->right_child){y->parent->right_child = x;}else{y->parent->left_child = x;}// 7.4设置y为x的右子节点x->right_child = y;// 7.5更新y的父节点为xy->parent = x;
}// last1.释放节点
void free_tree(rb_tree *tree, rb_tree_node *node)
{if (node != tree->nil_node){// 释放左子节点free_tree(tree, node->left_child);// 释放右子节点free_tree(tree, node->right_child);// 释放节点本身free(node);}
}// last2.释放树
void destroy_tree(rb_tree *tree)
{// 从root节点,根节点开始释放free_tree(tree, tree->root_node);// 释放哨兵节点free(tree->nil_node);// 释放红黑树的内存空间free(tree);
}
3. main.c
#include <stdio.h>
#include "../inc/rb_tree_common.h"int main(int argc, char const *argv[])
{//1.创建红黑树rb_tree *tree=create_rb_tree();//last.2 释放红黑树destroy_tree(tree);return 0;
}
4. 总结
1. 左右旋

左旋右旋,这层代码还是简单的,我想执导的是左右转的目的是什么,或者说在现实世界的应用情况
  在什么情况下可以用到左右旋?----在修复的时候用得到,要维护红黑树的平衡及规则

  左右旋转,先维护x与y的关系,即谁是谁的分支,重新定义x与y的双向关系


  1.先判断子结点
  上升的的节点与源节点的子关系,上升节点的分支与源节点的子关系
  2.判断父关系
(分支节点的的父节点)上升节点的某个分支不为哨兵节点的话,则判断其分支节点的指向为源节点(认爹)y->left_child->parent=x;
  x与y的关系有三种可能性
  1.x(源节点)为根节点,判断(x->parent==tree->nil_node),则y就等于根节点,即tree->root_node=y;
  2.即x不是根节点,判断x是其父节点的那个位置的节点,然后执行x->parent->left_child=y;
  3.另一个节点一样

2. 修复(变色,左右旋转)

这个我不知道怎么去描述。等有图了继续说

通过颜色翻转,将红色冲突向上传递,保证局部黑高不变,但可能引发更高层的红红冲突,需继续循环处理。

http://www.xdnf.cn/news/5928.html

相关文章:

  • 腾讯优化DeepSeek的DeepEP通信框架:开启AI大模型训练新时代
  • 股指期货是什么?有啥特点?怎么用?
  • 鸿蒙 Core File Kit(文件基础服务)之简单使用文件
  • 常时间运行的程序 导致系统卡顿 自动监控系统CPU和内存利用率 自动选择 内存回收 软件重启 电脑重启
  • 养生:拥抱健康生活的有效之道
  • eward hacking 问题 强化学习钻空子
  • MQTT协议技术详解:深入理解物联网通信基础
  • 项目管理系统供应链:打造高效运营“强引擎”
  • vsomeip环境搭建保姆级教程
  • Python训练打卡Day23
  • Java jar包程序 启动停止脚本 shell bash
  • 数据分析预备篇---Pandas的Series
  • Easysearch 时序数据的基于时间范围的合并策略
  • 软考软件测评师——计算机网络
  • MySQL历史版本下载及安装配置教程
  • GPT 经验
  • javax.servlet.Filter 介绍-笔记
  • 数字经济发展对“一带一路”地区农产品贸易效率的影响:基于空间溢出效应的视角
  • 数据分析文章目录
  • PyTorch的dataloader制作自定义数据集
  • 机器学习之决策树与决策森林:机器学习中的强大工具
  • Matlab基于SSA-MVMD麻雀算法优化多元变分模态分解
  • [特殊字符]CentOS 7.6 安装 JDK 11(适配国内服务器环境)
  • 【华为】现场配置OSPF
  • Axure应用交互设计:表格跟随菜单移动效果(超长表单)
  • 软件的价值维度
  • GraspVLA:基于Billion-级合成动作数据预训练的抓取基础模型
  • DIFY教程第七弹:Echarts可视化助手生成图表
  • 按键精灵ios脚本新增元素功能助力辅助工具开发(三)
  • 五大静态博客框架对比:Hugo、Hexo、VuePress、MkDocs、Jekyll