解构 AVL 树:平衡核心、旋转策略与高效实现技巧

作者:草莓熊Lotso日期:2025/11/24

🔥草莓熊Lotso:个人主页

❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》

✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:


文章目录

  • 前言:
  • 一. AVL 树核心概念:什么是 “高度平衡”?
  • 二. AVL 树结构设计:节点与类定义
  • 三. AVL 树插入:从 BST 插入到平衡维护
    • 3.1 插入完整代码(带详细注释)
    • 3.2 平衡因子更新关键逻辑
  • 四. AVL 树旋转:失衡恢复的四种方式
    • 4.1 右单旋(RotateR):左子树过高(父 BF=-2,子 BF=-1)
    • 4.2 左单旋(RotateL):右子树过高(父 BF=2,子 BF=1)
    • 4.3 左右双旋(RotateLR):左子树的右子树过高(父 BF=-2,子 BF=1)
    • 4.4 右左双旋(RotateRL):右子树的左子树过高(父 BF=2,子 BF=-1)
  • 五. AVL树的查找和平衡检查:验证树的正确性
    • 5.1 AVL树的查找:(与二叉搜索树一致,O(logN))
    • 5.2 AVL 树验证:如何判断实现正确?
  • 结尾:

前言:

在二叉搜索树(BST)中,若插入顺序有序(如递增或递减),树会退化为链表,导致增删查效率从
O(logN) 骤降至 O(N)。为解决这一问题,AVL 树(自平衡二叉搜索树)应运而生 —— 它通过控制左右子树的高度差(平衡因子),确保树始终保持 “高度平衡”,从而稳定维持 O(logN)的高效操作。本文将从 AVL 树的核心概念切入,结合完整代码实现,详解插入逻辑、平衡因子更新与四种旋转操作,帮你彻底掌握这一经典数据结构。


一. AVL 树核心概念:什么是 “高度平衡”?

AVL 树是一种特殊的二叉搜索树,满足两个核心条件:

  • 二叉搜索树特性:左子树所有节点值 < 根节点值 < 右子树所有节点值;
  • 高度平衡特性:任意节点的左右子树高度差的绝对值 ≤ 1。

为了更直观判断平衡状态,引入了平衡因子(balance factor):平衡因子 = 右子树高度 - 左子树高度
AVL 树中,任意节点的平衡因子只能是 -1、0、1;若平衡因子为 2 或 -2,说明树已失衡,需通过 “旋转” 恢复平衡。

思考:为什么不要求平衡因子为 0?
某些场景下(如 2 个节点、4 个节点),树无法做到左右子树高度完全相等(如根节点左子树高 1,右子树高 0),此时平衡因子为 1,仍满足 “高度差≤1” 的平衡要求。


二. AVL 树结构设计:节点与类定义

AVL 树的节点需存储键值对左右孩子指针父指针(用于更新平衡因子)和平衡因子。类定义如下:

1#pragma once
2#include<iostream>
3#include<assert.h>
4using namespace std;
5
6// AVL树节点的结构
7template<class K, class V>
8struct AVLTreeNode
9{
10    pair<K, V> _kv; // 存储键值对(Key-Value)
11    AVLTreeNode<K, V>* _parent; // 父节点指针(后续更新平衡因子要用到)
12    AVLTreeNode<K, V>* _left;        
13    AVLTreeNode<K, V>* _right;       
14    int _bf; // 平衡因子:右子树高度 - 左子树高度
15
16    AVLTreeNode(const pair<K, V>& kv)
17        : _kv(kv)
18        , _parent(nullptr)
19        , _left(nullptr)
20        , _right(nullptr)
21        , _bf(0)
22    {}
23};
24
25// AVL树类
26template<class K, class V>
27class AVLTree
28{
29    typedef AVLTreeNode<K, V> Node; 
30public:
31    // 插入、旋转等核心接口(下文会详细解析)
32    bool Insert(const pair<K, V>& kv);
33    void RotateR(Node* parent);  // 右单旋
34    void RotateL(Node* parent);  // 左单旋
35    void RotateLR(Node* parent); // 左右双旋
36    void RotateRL(Node* parent); // 右左双旋
37    Node* Find(const K& key);    // 查找(和二叉搜索树一样)
38    
39private:
40    Node* _root = nullptr; 
41};
42

三. AVL 树插入:从 BST 插入到平衡维护

AVL 树的插入流程分为两步:按 BST 规则插入节点回溯更新平衡因子失衡则旋转恢复。这是 AVL 树维持平衡的核心环节,需重点理解平衡因子的更新逻辑与停止条件。

3.1 插入完整代码(带详细注释)

1public:
2bool Insert(const pair<K,V>& kv)
3{
4	// 情况1:树为空,直接创建根节点
5	if (_root == nullptr)
6	{
7		_root = new Node(kv);
8		return true;
9	}
10	// 情况2:树非空,遍历找插入位置
11	Node* parent = nullptr;// 记录cur的父节点(用于后续链接新节点)
12	Node* cur = _root;
13	while (cur)
14	{
15		if (cur->_kv.first < kv.first)
16		{
17			parent = cur;
18			cur = cur->_right; // 比当前节点大,向右走
19		}
20		else if (cur->_kv.first > kv.first)
21		{
22			parent = cur;
23			cur = cur->_left;// 比当前节点小,向左走
24
25		}
26		else return false;// 值已存在,不支持插入,返回false
27	}
28
29	// 创建新节点,并链接到parent的左/右孩子
30	cur = new Node(kv);
31	if (parent->_kv.first < kv.first)
32	{
33		parent->_right = cur;// 插入值比parent大,作为右孩子
34	}
35	else {
36		parent->_left = cur; // 插入值比parent小,作为左孩子
37	}
38
39	cur->_parent = parent;
40
41	// 更新平衡因子(从新节点的父节点开始向上)
42	while (parent)
43	{
44		// 更新当前父节点的平衡因子
45		if (cur == parent->_left)
46		{
47			// 新节点在父节点的左子树  左子树高度+1  平衡因子-1
48			parent->_bf--;
49		}
50		else
51		{
52			// 新节点在父节点的右子树  右子树高度+1  平衡因子+1
53			parent->_bf++;
54		}
55
56		// 根据平衡因子判断是否继续更新或旋转
57		if (parent->_bf == 0)
58		{
59			// parent所在的子树高度不变,不会再影响上一层,更新结束
60			// 平衡因子变为0  父节点子树高度不变(插入前左 / 右高1,插入后平衡)
61			break;
62		}
63		else if (parent->_bf == 1 || parent->_bf == -1)
64		{
65			// parent 所在的子树高度变了,会再影响上一层,继续往上面更新
66			// 平衡因子变为1 / -1  父节点子树高度 + 1(插入前平衡,插入后单侧高1)
67			cur = parent;
68			parent = parent->_parent;
69		}
70		else if (parent->_bf == 2 || parent->_bf == -2)
71		{
72			// parent 所在的子树已经不平衡了,需要旋转处理
73			// 平衡因子变为2 / -1  父节点子树失衡,需旋转恢复平衡
74			if (parent->_bf == -2 && cur->_bf == -1)
75			{
76				// 父节点BF=-2(左子树高),当前节点BF=-1(左子树高)→ 右单旋
77				RotateR(parent);
78			}
79			else if (parent->_bf == 2 && cur->_bf == 1)
80			{
81				// 父节点BF=2(右子树高),当前节点BF=1(右子树高)→ 左单旋
82				RotateL(parent);
83			}
84			else if (parent->_bf == -2 && cur->_bf == 1)
85			{
86				// 父节点BF=-2(左子树高),当前节点BF=1(右子树高)→ 左右双旋
87				RotateLR(parent);
88			}
89			else
90			{
91				// 父节点BF=2(右子树高),当前节点BF=-1(左子树高)→ 右左双旋
92				RotateRL(parent);
93			}
94			// 旋转后,失衡子树高度恢复到插入前,不会影响上层,更新结束
95			break;
96		}
97		else
98		{
99			// 异常情况:平衡因子为其他值(如3、-3)
100			assert(false);
101		}
102	}
103	return true;
104}
105

3.2 平衡因子更新关键逻辑

更新平衡因子时,核心是判断 “当前子树高度是否变化”,进而决定是否继续向上更新:

  • BF=0:插入前父节点子树 “有一侧高 1”(如 BF=1 或 - 1),插入后两侧平衡,高度不变 → 停止更新;
  • BF=1/-1:插入前父节点子树 “平衡”(BF=0),插入后 “有一侧高 1”,高度 + 1 → 继续更新;
  • BF=2/-2:插入前父节点子树 “有一侧高 1”,插入后 “有一侧高 2”,失衡 → 旋转后停止更新。
  • 更新到根,根的平衡因子是1或-1也停止。

我们来看看下面几个情况图示:

更新到 10 结点,平衡因子为2,10所在的子树已经不平衡,需要旋转处理

更新到中间结点,3为根的子树高度不变,不会影响上一层,更新结束。

最坏情况:更新到根为止


四. AVL 树旋转:失衡恢复的四种方式

当节点平衡因子为 2- 2 时,需通过 “旋转” 恢复平衡。旋转的核心目标有两个:维持二叉搜索树特性 + 降低失衡子树高度。根据失衡形态,分为四种旋转方式

4.1 右单旋(RotateR):左子树过高(父 BF=-2,子 BF=-1)

  • 下图中展现的是10为根的树,有a/b/c抽象为三颗高度为h的子树(h>=0),a/b/c均符合AVL树的要求。10可能是整颗树的根。这里a/b/c是高度为h的子树,是一种概括抽象的表示,他代表了所有右单旋的场景,但实际右单旋的场景很多,大家可以看看后面的实际场景图。

  • 在 a 子树中插入一个新结点,导致a子树的高度从h变成h+1,不断向上更新平衡因子,导致10的平衡因子从-1变成-2,10为根的树左右高度差超过1,违反平衡规则。10为根的树的左边太高了,需要往右边旋转,控制两颗树的平衡。

旋转核心步骤

  1. 记录父节点(parent)的左子树(subL)和 subL 的右子树(subLR);
  2. 将 subLR 作为 parent 的左子树(若 subLR 非空,更新其 parent 指针);
  3. 将 parent 作为 subL 的右子树,更新 parent 的 parent 指针(提前存一下祖父结点,再更新);
  4. 链接 subL 与祖父节点(若 parent 是根节点,更新_root);
  5. 重置 parent 和 subL 的平衡因子为 0。

实际场景图
代码实现(注意看注释)

1public:
2void RotateR(Node* parent)
3{
4	Node* subL = parent->_left; // parent的左子树(即将成为新根)
5	Node* subLR = subL->_right; // subL的右子树(需转移给parent)
6
7	// 步骤1:将subLR作为parent的左子树
8	parent->_left = subLR;
9	if (subLR)
10		subLR->_parent = parent;
11
12	Node* grandparent = parent->_parent; // parent的父节点(祖父节点)
13
14	// 步骤2:将parent作为subL的右子树
15	subL->_right = parent;
16	parent->_parent = subL;
17
18	// 步骤3:链接subL与祖父节点(或更新根节点)
19	if (parent == _root)
20	{
21		// parent是根节点,则subL成为新根
22		_root = subL;
23		subL->_parent = nullptr;
24	}
25	else {
26		// parent是祖父节点的左/右孩子,对应链接subL
27		if (grandparent->_left == parent)
28			grandparent->_left = subL;
29		else
30			grandparent->_right = subL;
31			
32			subL->_parent = grandparent;
33		}
34
35	// 步骤4:重置平衡因子(旋转后子树平衡,BF均为0)
36	parent->_bf = subL->_bf = 0;	
37}
38

4.2 左单旋(RotateL):右子树过高(父 BF=2,子 BF=1)

  • 下图中展示的是10为根的树,有a/b/c抽象为三颗高度为h的子树(h>=0),a/b/c均符合AVL树的要求。10可能是整颗树的根,也可能是一整颗树中局部的子树的根。这里a/b/c是高度为h的子树,是一种概括抽象表示,他代表所有左单旋的场景,实际左单旋场景有很多,具体跟上面的右旋类似。
  • 在a子树中插入一个新结点,导致a子树的高度从h变成h+1,不断向上更新平衡因子,导致10的平衡因子从1变成2,10为根的树左右高度差超过1,违反平衡规则。10为根的树右边太高了。需要往左边旋转,控制两颗树的平衡。

旋转核心步骤

  • 记录父节点(parent)的右子树(subR)和 subR 的左子树(subRL);
  • 将 subRL 作为 parent 的右子树(若 subRL 非空,更新其 parent 指针);
  • 将 parent 作为 subR 的左子树,更新 parent 的 parent 指针(提前存一下祖父结点,再更新);
  • 链接 subR 与祖父节点(或更新_root);
  • 重置 parent 和 subR 的平衡因子为 0。

代码实现(注意看注释)

1public:
2void RotateL(Node* parent)
3{
4	Node* subR = parent->_right; // parent的右子树(即将成为新根)
5	Node* subRL = subR->_left;  // subR的左子树(需转移给parent)
6		
7	// 步骤1:将subRL作为parent的右子树
8	parent->_right = subRL;
9	if (subRL)
10		subRL->_parent = parent;
11		
12		Node* grandparent = parent->_parent; // parent的父节点
13
14	// 步骤2:将parent作为subR的左子树
15	subR->_left = parent;
16	parent->_parent = subR;
17
18	// 步骤3:链接subR与祖父节点(或更新根节点)
19	if (parent == _root)
20	{
21		_root = subR;
22		subR->_parent = nullptr;
23	}
24	else
25	{
26		if (grandparent->_left == parent)
27			grandparent->_left = subR;
28		else
29			grandparent->_right = subR;
30
31		subR->_parent = grandparent;
32	}
33
34	// 步骤4:重置平衡因子
35	parent->_bf = subR->_bf = 0;
36}
37

4.3 左右双旋(RotateLR):左子树的右子树过高(父 BF=-2,子 BF=1)

  • 我们通过下面这两种场景图,可以看出,左边高时,如果插入位置不是在a子树,而是插入到b子树,b子树高度从h变成h+1,引发了旋转,右单旋无法解决问题,右单旋过后,我们的树依旧不平衡。右单旋解决的纯粹的左边高,但是插入到b子树中,10为根的子树不再是单纯的左边高,对于10是左边高,但是对于5是右边高,需要用两次旋转才能解决,以5为旋转点进行一个左单旋,以10为旋转点进行一个右单旋,这颗树就平衡了。

  • 上面两个图片分别为左右双旋中 h==0h==1的具体场景分析,下面我们将a/b/c子树抽象为高度h的AVL子树进行分析,另外我们需要把b子树的细节进一步展开为8和左子树高度为h-1的e和f子树,因为我们要对b的父亲5为旋转点进行左单旋,左单旋需要动b树中的左子树。b子树中新增结点的位置不同,平衡因子更新的细节也不同,通过观察8的平衡因子不同,这里我们要分三个场景讨论。

旋转核心步骤

  • 对父节点的左子树(subL)执行左单旋(将 subL 的右子树 subLR 提升为 subL 的父节点);
  • 对父节点(parent)执行右单旋(将修正后的 subL 提升为 parent 的父节点);
  • 根据 subLR 的原始平衡因子,重置三个节点(parent、subL、subLR)的平衡因子,三种场景。
    • 场景1:h>=1时,新增结点插入在e子树,e子树高度从h-1变为h并不断更新 subLR->subL->parent 平衡因子,引发旋转,其中subLR的平衡因子为 -1,旋转后subLR和subL平衡因子为0,parent的平衡因子为1。
    • 场景2:h>=1时,新增结点插入在f子树,f子树高度从h-1变为h并不断更新 subLR->subL->parent 平衡因子,引发旋转,其中subLR的平衡因子为1,旋转后subLR和parent的平衡因子为0,subL的平衡因子为-1。
    • 场景3:h==0时,a/b/c都是空树,b自己就是一个新增结点,不断更新 subL->parent 平衡因子,引发旋转,其中subLR的平衡因子为0,旋转后subLR,subL和parent的平衡因子都为0。


代码实现(注意看注释)

1void RotateLR(Node* parent)
2{
3	Node* subL = parent->_left;  // parent的左子树
4	Node* subLR = subL->_right;  // subL的右子树(关键节点,决定平衡因子重置)
5	int bf = subLR->_bf;         // 记录subLR的原始BF(用于后续重置)
6
7	// 步骤1:先对subL执行左单旋(修正左子树的失衡)
8	RotateL(parent->_left);
9	// 步骤2:再对parent执行右单旋(修正父节点的失衡)
10	RotateR(parent);
11
12	// 步骤3:根据subLR的原始BF,重置三个节点的平衡因子
13	if (bf == 0)
14	{
15		// 场景3:subLR是新插入节点(BF=0)→ 旋转后三者BF均为0
16		parent->_bf = 0;
17		subL->_bf = 0;
18		subLR->_bf = 0;
19	}
20	else if (bf == 1)
21	{
22		// 场景2:subLR的右子树高(BF=1)→ parent的左子树高,subL的右子树高
23		parent->_bf = 0;
24		subL->_bf = -1;
25		subLR->_bf = 0;
26	}
27	else if(bf==-1)
28	{
29		// 场景1:subLR的左子树高(BF=-1)→ parent的右子树高,subL的左子树高
30		parent->_bf = 1;
31		subL->_bf = 0;
32		subLR->_bf = 0;
33	}
34	else
35	{
36		assert(false);
37	}
38}
39

4.4 右左双旋(RotateRL):右子树的左子树过高(父 BF=2,子 BF=-1)

  • 跟左右双旋类似,下面我们将a/b/c子树抽象为高度h的AVL子树进行分析,另外我们需要把b子树的细节进一步展开为12和左子树高度为h-1的e和f子树,因为我们要对b的父亲15为旋转点进行右单旋,右单旋需要动b树中的右子树。b子树中新增结点的位置不同,平衡因子更新的细节也不同,通过观察12的平衡因子不同不同,这里我们要分三个场景讨论。

旋转核心步骤

  • 对父节点的右子树(subR)执行右单旋;
  • 对父节点(parent)执行左单旋;
  • 根据 subRL 的原始平衡因子,重置三个节点的平衡因子。
    • 场景1:h>=1时,新增结点插入在e子树,e子树高度从h-1变为h并不断更新 subRL->subR->parent 平衡因子,引发旋转,其中subRL的平衡因子为-1,旋转后parent和subRL平衡因子为0,subR平衡因子为1。
    • 场景2:h>=1时,新增结点插入在f子树,f子树高度从h-1变为h并不断更新 subRL->subR->parent 平衡因子,引发旋转,其中subRL的平衡因子为1,旋转后subR和subRL的平衡因子为0,parent的平衡因子为-1。
    • 场景3:h==0时,a/b/c都是空树,b自己就是一个新增结点,不断更新**subR->parent** 平衡因子,引发旋转,其中subRL的平衡因子为0,旋转后三者的平衡因子都是0。


代码实现(注意看注释)

1void RotateRL(Node* parent)
2{
3	Node* subR = parent->_right; // parent的右子树
4	Node* subRL = subR->_left;   // subR的左子树(关键节点)
5	int bf = subRL->_bf;         // 记录subRL的原始BF
6
7	// 步骤1:先对subR执行右单旋(修正右子树的失衡)
8	RotateR(parent->_right);
9	// 步骤2:再对parent执行左单旋(修正父节点的失衡)
10	RotateL(parent);
11
12	// 步骤3:根据subRL的原始BF,重置三个节点的平衡因子
13	if (bf == 0)
14	{
15		// 场景3:subRL是新插入节点  三者BF均为0
16		subR->_bf = 0;
17		subRL->_bf = 0;
18		parent->_bf = 0;
19	}
20
21	else if (bf == 1)
22	{
23		// 场景2:subRL的右子树高(BF=1)→ parent的左子树高,subR的左子树高
24		subR->_bf = 0;
25		subRL->_bf = 0;
26		parent->_bf = -1;
27	}
28	else if (bf == -1)
29	{
30		// 场景1:subRL的左子树高(BF=-1)→ parent的右子树高,subR的右子树高
31		subR->_bf = 1;
32		subRL->_bf = 0;
33		parent->_bf = 0;
34	}
35	else
36	{
37		// 异常情况
38		assert(false);
39	}
40}
41

五. AVL树的查找和平衡检查:验证树的正确性

5.1 AVL树的查找:(与二叉搜索树一致,O(logN))

1Node* Find(const K& key)
2{
3	Node* cur = _root;
4	while (cur)
5	{
6		if (cur->_kv.first < key)
7		{
8			cur = cur->_right;
9		}
10		else if (cur->_kv.first > key)
11		{
12			cur = cur->_left;
13		}
14		else
15		{
16			return cur;
17		}
18	}
19	return nullptr;
20}
21

5.2 AVL 树验证:如何判断实现正确?

为确保 AVL 树实现无误,需验证两个核心条件:二叉搜索树特性 + 高度平衡特性。可添加以下辅助接口(类内补充):

1public:
2	// 对外接口:验证AVL树
3	bool IsBalanceTree()
4	{
5		return _IsBalance(_root);
6	}
7
8	// 对外接口:中序遍历(验证二叉搜索树特性:中序递增)
9	void InOrder()
10	{
11		_InOrder(_root);
12		cout << endl;
13	}
14
15private:
16	void _InOrder(Node* root)
17	{
18		if (root == nullptr)
19			return;
20		_InOrder(root->_left);
21		cout << root->_kv.first << " ";
22		_InOrder(root->_right);
23	}
24

测试代码示例

1#define _CRT_SECURE_NO_WARNINGS 1
2#include"AVLTree.h"
3
4// 测试AVL树插入与平衡性
5void TestAVL()
6{
7    // 测试用例1:包含双旋场景(如4,2,6,1,3,5,15,7,16,14)
8    int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
9    AVLTree<int, int> t;
10    for (auto e : a)
11    {
12        t.Insert({ e, e });
13    }
14
15    // 验证1:中序遍历(应递增)
16    cout << "中序遍历结果:";
17    t.InOrder(); // 输出:1 2 3 4 5 6 7 14 15 16
18
19    // 验证2:平衡性(应返回true)
20    if (t.IsBalanceTree())
21    {
22        cout << "AVL树平衡验证通过!" << endl;
23    }
24    else
25    {
26        cout << "AVL树平衡验证失败!" << endl;
27    }
28}
29
30int main()
31{
32    TestAVL();
33    return 0;
34}
35


声明:AVL树的删除这里不做讲解,有兴趣的朋友可参考:《殷人昆 数据结构:用面向对象方法与C++语言描述》中讲解。


结尾:

1🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
2👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
3❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
4 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
5💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
6🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
7技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!
8

结语:AVL 树以 “平衡因子” 控平衡、“旋转操作” 修失衡,将增删查效率稳定在(O(log N)),是自平衡树的经典范式。其核心魅力在于用简洁的平衡逻辑(高度差≤1)和精准的旋转策略,化解普通二叉搜索树退化的问题,虽高频写场景下旋转开销略逊于红黑树,但对平衡原理的直观呈现,使其成为理解复杂自平衡结构的基石。吃透 AVL 树的平衡传递与旋转细节,不仅能掌握一种高效数据结构,更能建立 “以主动维护换性能稳定” 的思维,为后续进阶打下基础。

✨把这些内容吃透超牛的!放松下吧✨

ʕ˘ᴥ˘ʔ

づきらど


解构 AVL 树:平衡核心、旋转策略与高效实现技巧》 是转载文章,点击查看原文


相关推荐


CSE服务治理实践:负载均衡
高校俱乐部2025/11/22

1 概述 1.1 背景介绍 微服务引擎CSE,是用于微服务应用的云中间件,支持华为云贡献到Apache社区的注册配置中心Servicecomb引擎和开源增强的注册配置中心Nacos引擎。用户可结合其他云服务,快速构建云原生微服务体系,实现微服务应用的快速开发和高可用运维。 1.2 适用对象 企业个人开发者高校学生 1.3 案例时间 本案例总时长预计30分钟。 1.4 案例流程 说明: ① 在云主机上搭建CSE本地开发工具; ② 改造E-Commerce-one代码,并启动E-C


【codex】使用 PLANS.md 进行长时间问题解决
是魔丸啊2025/11/20

转载 Codex 和 gpt-5-codex 模型能够用于实现需要大量时间进行研究、设计和开发的复杂任务。本文介绍的方法是引导模型实现这些任务并促使其成功完成项目的一种有效方式。 这些计划既是详尽的设计文档,也是"动态文档"。作为 Codex 的使用者,您可以借助这些文档来审核 Codex 在启动漫长开发流程前所采取的实施方法。下文包含的 PLANS.md 与让 Codex 能够通过单次提示连续工作超过七小时的文档版本非常相似。 我们通过首先更新 AGENTS.md 来说明何时使用 PLANS.


基于C++的游戏引擎开发
普通网友2025/11/19

1、非修改序列算法 这些算法不会改变它们所操作的容器中的元素。 1.1 find 和 find_if find(begin, end, value):查找第一个等于 value 的元素,返回迭代器(未找到返回 end)。find_if(begin, end, predicate):查找第一个满足谓词的元素。find_end(begin, end, sub_begin, sub_end):查找子序列最后一次出现的位置。 vector<int> nums = {1, 3, 5, 7, 9};


Python 的内置函数 vars
IMPYLH2025/11/17

Python 内建函数列表 > Python 的内置函数 vars Python 的内置函数 vars() 是一个非常有用的工具函数,主要用于返回对象的 __dict__ 属性。它可以应用于模块、类、实例以及其他具有 __dict__ 属性的对象。以下是关于 vars() 函数的详细说明: 基本用法 不带参数调用: 当 vars() 不带参数调用时,它等同于 locals() 函数,返回当前局部作用域的符号表(通常是当前函数的局部变量)。 def example(): x = 1


Python 的内置函数 reversed
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 reversed Python 的内置函数 reversed() 是一个用于序列反转的高效工具函数,它返回一个反向迭代器对象。以下是关于该函数的详细说明: 基本用法 语法:reversed(seq)参数:seq 可以是任何实现了 __reversed__() 方法的对象,或者支持序列协议(__len__() 和 __getitem__() 方法)的对象返回值:返回一个反向迭代器对象 支持的数据类型 列表:reversed([1,


Python 的内置函数 min
IMPYLH2025/11/15

Python 内建函数列表 > Python 的内置函数 min Python 的内置函数 min() 是一个非常有用的工具函数,用于返回给定参数中的最小值。这个函数可以接受两种形式的参数: 多个单独的参数 min(a, b, c, ...) 它会返回这些参数中的最小值。 一个可迭代对象(如列表、元组、集合等) min(iterable, *[, key, default]) 它会遍历可迭代对象,并返回其中的最小值。 参数说明: iterable:必须是一个可迭代对象(如列表、元


12 节课解锁 AI Agents,让AI替你打工(一): 简介
AI大模型2025/11/14

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI。 本系列教程主要是为了探索 AI Agent 的设计原理与真实世界应用 随着大语言模型(LLMs)的出现,人工智能取得了巨大飞跃。这些强大的系统彻底改变了自然语言处理,但当它们与智能体(即自主推理、规划和行动的能力)相结合时,其真正潜力才得以释放。这就是大语言模型智能体发挥作用的地方,它代表了我们与人工智能交互和利用方式的范式转变。 图片来源:letta 本文旨在全面概述 AI Agent,深入探讨其特征、组件和类


Lua 的 Coroutine 模块
hubenchang05152025/11/13

#Lua 的 Coroutine 模块 请查看 Lua 标准库模块列表 了解更多相关 API。 函数说明coroutine.create创建协程对象coroutine.close 关闭协程对象coroutine.resume恢复协程coroutine.yield让出协程coroutine.wrap创建协程对象,返回一个恢复函数coroutine.isyieldable检查协程能否让出coroutine.running获取正在运行的协程对象coroutine.status获取协程状态 Lua


Node.js 开发环境搭建全攻略(2025版)
Java私教2025/11/11

本文将详细介绍如何在本地搭建一个高效、可维护的 Node.js 开发环境,适用于 Windows、macOS 与 Linux。无论你是后端新手还是资深全栈工程师,都能通过本文快速构建一个标准化的 Node.js 开发环境。 一、什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它让开发者可以在服务器端运行 JavaScript。 它以 事件驱动、非阻塞 I/O 的特性著称,非常适合构建高性能的 Web 服务和微服务架构。 二、安


类比前端知识来学习Java的Spring Boot实现MySql的全栈CRUD功能——搭配Svelte+Vite
水冗水孚2025/11/9

前言 本文梳理了后端的相关操作流程环节 使用Svelte+Vite(前端)搭配Spring Boot(后端) 实现了一个增删改查全栈项目 有助于前端更好理解后端java的分层思想,数据流转控制 和Svelte尝鲜学习了解 完整前后端代码在github:github.com/shuirongshu… 大道至简,一些知识点是相通的比如——python里面也有闭包这个概念 所谓编程即:学习规则语法、理解规则语法、合理运用规则语法、从而自定义规则... Java、Spring、Spring Bo

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读