算法导论学习---红黑树详解之插入(C语言实现)

本文深入探讨了红黑树的性质,并详细介绍了如何通过C语言实现红黑树的插入操作。通过左旋和右旋来维护树的平衡,确保动态集合操作能在O(logn)时间内完成。文章提供了插入操作的代码示例,并分析了插入调整函数RBInsertFixUp()的逻辑,确保红黑树性质得到恢复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面我们学习二叉搜索树的时候发现在一些情况下其高度不是很均匀,甚至有时候会退化成一条长链,所以我们引用一些”平衡”的二叉搜索树。红黑树就是一种”平衡”的二叉搜索树,它通过在每个结点附加颜色位和路径上的一些约束条件可以保证在最坏的情况下基本动态集合操作的时间复杂度为O(nlgn).下面会总结红黑树的性质,然后分析红黑树的插入操作,并给出一份完整代码。

先给出红黑树的结点定义:

#define RED 1
#define BLACK 0

///红黑树结点定义,与普通的二叉树搜索树相比多了一个颜色域
typedef struct node
{
      int key,color; ///定义1为红,0为黑
      node *p,*left,*right;
      node(){
         color=BLACK; ///默认结点颜色为黑
      }
}*RBTree;

一.从红黑树的性质讲起
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过堆任何一条从根到叶子结点的简单路径上各个结点颜色进行约束,红黑树确保没有一条路径会比其它路径要长出两倍,因而是近似于平衡的。下面给出红黑树的五条”红黑性质”,这几条性质是后面插入和删除的基础。
1).每个结点或是红色或是黑色。
2).根结点是黑色的。
3).每个叶结点是黑色的
4).如果一个结点是红色的,那么它的两个子节点都是黑色的。
5).对于每个结点,从该结点出发到其所有后代叶结点的简单路径上均包含相同数目的黑结点。
我们设从某个结点x出发(不含该结点)到达一个叶结点的一条简单路径上的黑结点个数为该结点的黑高,记为bh(x)。显然根据性质5,每个结点的黑高都是唯一的。下面我们来证明:一棵含有n个内部结点的红黑树的高度至多为2lg(n+1).
先证明以任一结点x为根的子树中至少包含2^bh(x)-1个内部结点。我们采用数学归纳法,对x的黑高进行归纳。如果x的黑高高度为0即x为叶子结点,则显然正确。x的黑高为bh(x),则其两棵子树的黑高为bh(x)或bh(x)-1(取决与它们本身的颜色),则可归纳出对应的内部结点至少为2^(bh(x)-1)-1,即x包含的内部结点至少为2^(bh(x)-1)-1+2^(bh(x)-1)-1+1=2^bh(x)-1,因此得证。然后现在我们设含n个结点的树高为h,然后根据性质4,可以知道从根到叶结点(不包括根结点)的任一条简单路径上都至少有一半的结点为黑色。因此树的黑高至少为h/2;然后有上面的结论得n>=2^(h/2)-1.解得h<=2lg(n+1)。于是我们就证明了动态集合操作Search,Minimum,Successor等都可以在O(lgn)时间复杂度内完成了。

下面给一张红黑树的图片。
这里写图片描述

二.旋转操作
后面的插入和删除过程中都会有破坏红黑树性质的情况发送,为了维护这些性质,必须要改变树中某些结点的颜色和指针结构。指针结构的修改是通过旋转来完成的,旋转被分为左旋和右旋;在插入和删除操作中这两个操作会多次出现,我们先来分析一下这两个操作。
这两个操作对应的图像如下:
这里写图片描述

从图像上可以看出,左旋和右旋操作并不是很复杂。下面我们以左旋为例进行解析:如图我们假设结点x的右儿子为y。左旋的前提是:结点必须要有右儿子。左旋的结果是:y代替x,x成为y的左儿子,x成为y的左儿子,y的左儿子成为x的右儿子。下面是具体的代码实现:

///左旋:对具有任意具有右孩子的结点可以进行
///传入要选择的结点指针的引用
///旋转以后x的右孩子y取代了x,而x成为y的左孩子,y的左孩子成为x的右孩子
///下面的代码就是完成这三个部分
void LeftRotate(RBTree x)
{
      RBTree y=x->right; ///y表示x的右孩子
      x->right=y->left; ///第一步:将x的右孩子设为y的左孩子
      if(y->left!=Nul)
            y->left->p=x;

     y->p=x->p;  ///更改y的父结点为x的父结点
      if(x->p
<think>嗯,用户正在准备考研数据结构科目,需要系统梳理知识点。从引用[1]看,考研要求明确分为四个层次:基本概念掌握、存储结构与算法分析能力、C/C++实现能力、综合应用能力。用户可能更关注考点分布和高效复习策略。 注意到用户两次提问都强调"知识点",说明需要结构化框架而非零散内容。引用中提到的选择题侧重概念理解(如静态链表在引用[2]中的数组实现形式),综合题侧重算法设计,这提示复习要区分层次。 用户上次提问已涵盖数据结构分类(线性/树/图/散列),这次应聚焦考研特有重点: 1. 时间/空间复杂度分析必须贯穿所有知识点,这是高频考点 2. 存储结构差异比较(如顺序表vs链表在插入删除时的性能对比) 3. 特定结构的考研经典题型:二叉树遍历的非递归实现、图的最短路径算法对比、哈希冲突处理等 需特别注意实践要求:引用[1]明确要求C/C++实现能力,示例代码用C语言,故推荐资源应包含动手实现环节(如链表逆置、二叉树层次遍历等常考代码片段)。 学习建议需要量化时间:基础阶段2周完成知识框架,强化阶段3周刷透真题,冲刺阶段1周查漏补缺。算法题要分题型训练,比如分治思想(归并排序)和贪心(Dijkstra)应单独突破。 最后生成的三个问题覆盖了用户潜在需求:复杂度分析是理论基础,存储结构是核心难点,应用场景则关联实际考题。特别是"如何选择合适数据结构"直接对应引用[1]中第三个考核目标。</think>根据考研数据结构科目的核心要求(引用[1]),以下是系统化的知识点框架和学习策略: ### 一、考研数据结构核心知识点体系 #### 1. **基础概念与原理** [^1] - **逻辑结构**:线性结构(数组/链表)、非线性结构(树/图) - **存储结构**: - 顺序存储(数组) - 链式存储(单链表/双向链表) - 索引存储 - 散列存储(哈希表) - **静态链表实现**(引用[2]): ```c #define MAXSIZE 100 typedef struct { ElemType data; int next; // 存储数组下标 } SLinkList[MAXSIZE]; ``` #### 2. **算法分析核心** - **时间复杂度计算**: - 循环嵌套:$T(n) = O(n^k)$ - 递归:$T(n) = aT(\frac{n}{b}) + f(n)$ - **空间复杂度**:递归深度 $O(\log n)$ vs $O(n)$ #### 3. **重点数据结构与操作** | **结构类型** | **核心操作** | **考研高频考点** | |--------------|-------------------------------|-----------------------------------| | 线性表 | 插入/删除(时间复杂度对比) | 链表逆置、合并有序表 | | 栈与队列 | 出入栈规则、循环队列实现 | 中缀表达式求值、双栈模拟队列 | | 树与二叉树 | 遍历(先序/中序/后序/层次) | 非递归遍历、线索二叉树构造 | | 图 | DFS/BFS、最短路径(Dijkstra) | 最小生成树(Prim/Kruskal)实现 | | 查找 | 二叉排序树、平衡二叉树调整 | B树特性、哈希冲突解决(拉链法) | | 排序 | 快速排序分区、堆排序调整 | 稳定性分析、外部排序归并策略 | #### 4. **算法设计能力** - **C/C++实现要点**: ```c // 二叉树非递归中序遍历(常考题型) void InOrder(BiTree T) { Stack S; InitStack(S); BiTree p = T; while (p || !StackEmpty(S)) { if (p) { Push(S, p); p = p->lchild; } else { Pop(S, p); visit(p->data); p = p->rchild; } } } ``` - **解题技巧**: - 链表题:快慢指针找中点 - 图论题:邻接表存储优化空间 - 排序题:识别有序片段减少比较 ### 二、高效学习路径 1. **基础阶段(4周)** - 精读《数据结构(严蔚敏)》+ 完成课后习题 - 手写实现所有基础结构(数组/链表/栈/队列) 2. **强化阶段(6周)** - 重点突破树与图算法(参考《算法导论》) - 刷透历年真题(推荐《王道考研数据结构》) 3. **冲刺阶段(2周)** - 专题训练: ```mermaid graph LR A[算法应用题] --> B[设计哈夫曼编码] A --> C[拓扑排序序列] A --> D[堆排序调整过程] ``` - 模拟考场环境限时编程 ### 三、关键学习资源 1. **教材** - 《数据结构(C语言版)》严蔚敏(配套习题详解-算法导论》第三版(重点看红黑树、动态规划) 2. **题库** - 王道论坛考研真题分类汇编 - LeetCode“数据结构”专项训练(标签:linked-list, tree) 3. **可视化工具** - VisuAlgo.net(动态演示算法执行过程) - Data Structure Visualizations(交互式操作练习) > **注**:考研算法题评分标准:时间复杂度占40%,空间优化占30%,代码规范性占30%[^1] --- ### 相关问题 1. **如何高效计算递归算法的时间复杂度?** 2. **树结构中,如何根据遍历序列重建二叉树?** 3. **图的最短路径算法中,Dijkstra和Floyd的区别及应用场景是什么?**
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值