如上图所示:
数据结构中按存储结构划分有四种:
1、 顺序存储:用一段地址连续的存储单元依次存储线性表的数据元素
常用的存储方式有:数组
2、 链式存储:地址可以连续也可以不连续的存储单元存储数据元素
常用的存储方式有:单向链表、双向链表、循环链表
3、 索引存储:分别存放数据元素和元素间关系的存储方式
常用的存储方式有:B-、B+ 树(常用在数据库存储方式中)
4、 散列存储:又称hash存储,是一种将数据元素的存储位置与关键码之间建立确定对应关系的查找技术
常用的存储方式有:Hash函数
数据结构中按元素之间前后关系划分为两种:
1、 线性结构:有且只有一个根结点,且每个结点最多有一个直接前驱和一个直接后继的非空数据结构;
2、 非线性结构:不满足线性结构的数据结构;
数组,链表
1、 数组:一组有序的元素序列;
2、 链表:一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的;
1)无头非循环单向链表:
结构简单,一般不会用来单独存放数据,实际应用中更多是作为其他数据结构的子结构,比如哈希桶;
2)带头循环双向链表:
结构复杂,一般用来单独存放数据,实际中经常使用的链表数据结构中,都是带头双向循环链表;
链表和数组的区别:
1) 数组静态分配内存,链表动态分配内存;
2) 数组在内存中是连续的,链表不是连续的;
3) 数组利用下标定位,查找的时间复杂度是O(1),链表通过遍历定位元素,查找的时间复杂度是O(N);
4) 数组插入和删除需要移动其它元素,时间复杂度是O(N),链表的插入和删除不需要移动其它元素,时间复杂度是O(1);
数组的优点:
1) 随机访问性比较强,可以通过下标进行快速定位;
2) 查找速度快;
数组的缺点:
1) 插入和删除的效率低,需要移动其它元素;
2) 会造成内存的浪费,因为内存是连续的;
3) 内存空间要求高,创建一个数组,必须要有足够的连续内存空间;
4) 数组的大小是固定的,不能动态拓展;
链表的优点:
1) 插入和删除的效率高,只需要改变指针的指向就可以进行插入和删除;
2) 内存利用率高,不会浪费内存,只有在需要的时候才去创建空间,拓展灵活;
链表的缺点:
1)查找的效率低,链表任何时候查找都是先从根结点开始向后遍历查找;
单链表和双链表的区别:
1) 单链表的每一个结点中只有指向下一个结点的指针,不能进行回溯;
2) 双链表的每一个结点中有指向下一个结点的指针,也有指向上一个结点的指针,适用于需要双向查找结点值的情况;
递归
1、 什么是递归:
递归在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。
通俗来讲,递归算法的实质是把问题分解成规模缩小的同类问题的子问题,然后递归调用方法来表示问题的解。
2、 递归的使用:
递归算法的第一步是分治,把复杂的大问题,给拆分成一个个小问题,直到不能再拆解,通过退出条件return。
然后再从最小的问题开始解决,直到所有的子问题都解决完毕,那么最终的大问题就迎刃而解。
3、 递归的基本原理:
a) 每一级的函数调用都有自己的变量。
b) 每一级函数调用都会有一次返回。
c) 递归函数中,位于递归调用前的语句和各级被调用函数具有相同的执行顺序。
d) 递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反。
e) 虽然每一级递归都有自己的变量,但是函数代码并不会得到复制。
4、 递归的优缺点:
a) 优点:实现简单,可读性好。
b) 递归调用,占用空间大。 递归太深,易发生栈溢出。 可能存在重复计算。
5、 递归的三大要素:
a) 明确这个函数想要干什么。
b) 寻找递归的结束条件(归)。
c) 找出函数的等价关系式(递)。
6、 递归的过程:
7、 递归的优化方法:
a) 考虑是否重复计算。
b) 考虑尾递归。
对于递归的问题,一般都是从上往下递归的,直到递归到最低,再一层一层着把值返回。
如果n比较大的时候,可能栈空间会不够用,这个时候就可以用尾递归优化来解决。
尾递归就是从最后开始计算,每递归一次就算出相应的结果。
二叉树
1、 树(Tree):
树是 n(n >= 0) 个结点的有限集,n=0 时称为空树,在任意一颗非空树中:
a) 有且仅有一个特定的称为根(Root)的结点。
b) 当 n > 1 时,其余结点可分为 m(m > 0) 个互不相交的有限集T1、T2、…… 、Tn,其中每一个集合本身又是一颗树,并且称为根的子树。
c) 当 n > 0 时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点。
d) 当 m > 0 时,子树的个数没有限制,但它们一定是互不相交的。
e) 结点拥有子树数目称为结点的**度**。
f) 树中结点的最大层次数称为树的**深度或高度**,下图中所示树的深度为 4。
2、二叉树(Binary Tree):
二叉树的定义:
二叉树是 n(n >= 0) 个结点的有限集合,该集合或者为空集(称为空二叉树)。
或者由一个根结点和两颗互不相交的、分别称为根结点的左子树和右子树组成。
二叉树的特点:
1) 每个结点最多有两颗子树,所以二叉树中不存在度大于2的结点。
2) 左子树和右子树是有顺序的,次序不能任意颠倒。
3) 即使树中某结点只有一颗子树,也要区分它是左子树还是右子树。
二叉树的性质:
1) 在二叉树的第 i 层上最多有 (2^i-1)个结点(i >= 1)。
2) 二叉树中如果深度为k,那么最多有 (2^k)\-1个结点(k >= 1)。
3) N = K + 1, N表示度数为0的结点数,K表示度数为2的结点数。
4) 在完全二叉树中,具有n个结点的完全二叉树的深度为 \[log2n\] + 1,其中 \[log2n\]是向下取整。
5) 若对含 n 个结点的**完全二叉树**从上到下且从左到右进行1至n的编号,则对完全二叉树中任意一个编号为 i 的结点有如下特性:
(1) 若 i = 1,则该结点是二叉树的根,无双亲。否则、编号为 \[i / 2\] 的结点为其双亲结点。
(2) 若 2i > n,则该结点无左孩子,否则编号为 2i 的结点为其左孩子结点。
(3) 若 2i + 1 > n,则该结点无右孩子,否则,编号为 2i + 1 的结点为其右孩子结点。
3、斜树:
斜树的定义:
所有的结点都只有左子树的二叉树叫左斜树,所有结点都只有右子树的二叉树叫右斜树。
4、满二叉树:
满二叉树的定义:
所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。
满二叉树的特点:
1) 叶子只能出现在最下一层。
2) 非叶子结点的度一定是2。
3) 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
5、完全二叉树:
注:满二叉树一定是完全二叉树,但反过来不一定成立。
对一颗具有n个结点的二叉树按层编号,如果编号为 i (1 <= i <= n)的结点与同样深度的满二叉树中编号为 i 的结点在二叉树中位置完全相同,则这颗二叉树称为完全二叉树。
完全二叉树的特点:
1) 叶子结点只能出现在最下层和次下层。
2) 最下层的叶子结点集中在树的左部。
3) 倒数第二层若存在叶子结点,一定在右部连续位置。
4) 如果结点度为1,则该结点只有左孩子,即没有右子树。
5) 同样结点数目的二叉树,完全二叉树深度最小。
6、二叉树的存储结构:
顺序存储(顺序存储一般适用于完全二叉树):
二叉树的顺序存储结构就是使用一维数组存储二叉树中的结点,并且结点的存储位置就是数组的下标索引。
链式存储:
采用一种链表结构存储二叉树,这种链表称为二叉链表。
7、二叉树遍历:
二叉树的遍历是指从二叉树的根结点出发,按照某种次序依次访问二叉树中的所有结点,使得每个结点被访问一次,且仅被访问一次。
前序遍历:
从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左再向右的方向访问。
中序遍历:
从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左再向右的方向访问。
后序遍历:
从二叉树的根结点出发,当第三次到达结点时就输出结点数据,按照先向左再向右的方向访问。
层次遍历:
从二叉树的根结点出发,按照树的层次自上而下的遍历二叉树。
下图中前序遍历:A B D H I E J C F G
下图中中序遍历:H D I B J E A F C G
下图中后序遍历:H I D J E B F G C A
下图中层次遍历:A B C D E F G H I J
8、 二叉树的插入:
每次添加数据的时候都是从根结点向下遍历。
a) 如果根结点为空,则新生成一个结点为根结点。
b) 如果根结点不为空,则根据二叉树的性质判断结点是左结点还是右结点。
c) 插入结点比当前结点小,把当前结点设置为左子结点,然后与左子结点比较,以此类推找到合适的位置。
d) 插入结点比当前结点大,把当前结点设置为右子结点,然后与右子结点比较,以此类推找到合适的位置。
e) 创建一个新结点,根据比较结果将新结点放入合适的位置。
9、 二叉树的删除:
第一种情况,删除结点没有子结点:
1) 删除结点为根结点,根结点置为null。
2) 删除结点为叶子结点,若删除结点为父结点的左子结点,则置父结点的左子结点为null,若删除结点为父结点右子结点,则置父结点的右子结点为null。
3) 将删除结点置null,等GC回收。
第二种情况,删除结点只有左子结点:
1) 删除结点为根结点,根结点置为null,将左子结点置为根结点。
2) 删除结点非根结点,将删除结点的父结点的左结点指向删除结点的左子结点,将左子结点指向删除结点的父结点。
第三种情况,删除结点只有右子结点:
1) 删除结点为根结点,根结点置为null,将右子结点置为根结点。
2) 删除结点非根结点,将删除结点的父结点的右结点指向删除结点的右子结点,将右子结点指向删除结点的父结点。
第四种情况,删除结点有两个子结点:
1) 按中序遍历的方式先查找删除结点的后继结点。
2) 使用后继结点替换删除结点,删除后继结点。
B树 和 B+树
1、 B树
B树的定义:
B树也称 B- 树(读B杠树),它是一颗多路平衡查找树描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母 m 表示阶数,当 m 取2时,就是常见的二叉树。
1) 每个结点最多有 m-1 个关键字。
2) 根结点最少可以只有1个关键字。
3) 非根结点至少有Math.ceil(m/2)-1个关键字。
4) 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
5) 所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。
B树的举例:
下图中是一颗阶数为4的B树,在实际应用中B树的阶数m都非常大(通常大于100),所以即使存储大量的数据,B树的高度仍然比较小,每个结点中存储了关键字(key)和关键字对应的数据(data),以及孩子结点的指针。
我们将一个key和其对应的data称为一个记录(key, value),在数据库中我们将B树(和B+树)作为索引结构,可以加快查询速度,此时B树中的key就表示键,而data表示了这个键对应的条目在硬盘上的逻辑地址。
B树的插入操作:
插入操作是指插入一条记录,即(key, value)的键值对。如果B树中已存在需要插入的键值对,则用需要插入的value替换旧的value,若B树不存在这个key,则一定是在叶子结点中进行插入操作。
1) 根据要插入的key的值,找到叶子结点并插入。
2) 判断当前结点key的个数是否小于等于m-1,若满足则结束,否则进行第3步。
3) 以结点中间的key为中心分裂成左右两部分,然后将这个中间的key插入到父结点中,这个key的左子树指向分裂后的左半部分,这个key的右子树指向分裂后的右半部分,然后将当前结点指向父结点,继续进行第3步。
B树的删除操作:
删除操作是指,根据key删除记录,如果B树中的记录中不存在对应key的记录,则删除失败。
1) 如果当前需要删除的key位于非叶子结点上,则用后继key(这里的后继key均指后继记录的意思)覆盖要删除的key,然后在后继key所在的子分支中删除该后继key,此时后继key一定位于叶子结点上,这个过程和二叉搜索树删除结点的方式类似,删除这个记录后执行第2步。
2) 该结点key个数大于等于Math.ceil(m/2)-1,结束删除操作,否则执行第3步。
3) 如果兄弟结点key个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束。
否则,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,行成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点,然后当前结点的指针指向父结点,重复上第2步。
2、 B+树
B+树的定义:
关键字个数比孩子结点个数小1,这种方式是和B树基本等价的,上图就是一颗阶数为4的B+树。
1) B+树中包含2种类型的结点:内部结点(也称索引结点)和叶子结点。根结点本身即可以是内部结点,也可以是叶子结点,根结点的关键字个数最少可以只有1个。
2) **B+****树与B树最大的不同是内部结点不保存数据,只用于索引,所有数据(或者说记录)都保存在叶子结点中。**
3) m阶B+树表示了内部结点最多有m-1个关键字(或者说内部结点最多有m个子树),阶数m同时限制了叶子结点最多存储m-1个记录。
4) 内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左子树中的所有key都小于它,右子树中的key都大于等于它,叶子结点中的记录也按照key的大小排列。
5) 每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接。
B+树的插入操作:
1) 若为空树,创建一个叶子结点,然后将记录插入其中,此时这个叶子结点也是根结点,插入操作结束。
2) 针对叶子类型结点,根据key值找到叶子结点,向这个叶子结点插入记录。插入后,若当前结点key的个数小于等于m-1,则插入结束。否则跳到步骤3。
3) 将这个叶子结点分裂成左右两个叶子结点,左叶子结点包含前m/2个记录,右结点包含剩下的记录,将第m/2 + 1个记录的key进位到父结点中(父结点一定是索引类型结点),进位到父结点的key左孩子指针指向左叶子结点,右孩子指针指向右叶子结点,将当前结点的指针指向父结点,然后执行第4步。
4) 针对索引类型结点,若当前结点key的个数小于等于m-1,则插入结束。否则跳到步骤5。
5) 将这个索引类型结点分裂成两个索引结点,左索引结点包含前(m-1)/2个key,右结点包含m – (m-1)/2个key,将第m/2个key进位到父结点中,进位到父结点的key左孩子指向左结点,进位到父结点的key右孩子指向右结点,将当前结点的指针指向父结点,然后重复第4步。
B+树的删除操作:
如果叶子结点中没有相应的key,则删除失败。
1) 删除叶子结点中对应的key,删除后若结点的key的个数大于等于Math.ceil(m-1)/2 – 1,删除操作结束,否则执行第2步。
2) 若兄弟结点key有富余(大于Math.ceil(m-1)/2 - 1),向兄弟结点借一个记录,同时用借到的key替换父结点中的key,删除结束,否则执行第3步。
3) 若兄弟结点中没有富余的key,则当前结点和兄弟结点合并成一个新的叶子结点,并删除父结点中的key(父结点中的这个key两边的孩子指针就变成了一个指针,正好指向这个新的叶子结点),将当前结点指向父结点(必为索引结点),执行第4步(第4步的操作和B树就完全一样了,主要是为了更新索引结点)。
4) 若索引结点的key的个数大于等于Math.ceil(m-1)/2 – 1,则删除操作结束,否则执行第5步。
5) 若兄弟结点富余,父结点key下移,兄弟结点key上移,删除结束。否则执行第6步。
6) 当前结点和兄弟结点及父结点下移key合并成一个新的结点,将当前结点指向父结点,重复第4步。
红黑树
JDK 1.8 中的HashMap 中使用红黑树进行存储,红黑树的插入与删除是一个递归调用的过程;
红黑树的定义和性质:
1) 每个结点要么是黑色,要么是红色;
2) 根结点是黑色;
3) 每个叶子结点(NIL)是黑色;
4) 每个红色结点的两个子结点一定都是黑色;
5) 任意一结点到每个叶子结点的路径都包含数量相同的黑结点;
从性质5可以推断出性质5.1: 如果一个结点存在黑子结点,那么该结点肯定有两个子结点;
下图就是一颗简单的红黑树,其中Nil为叶子结点,并且它是黑色的;
注意:在Java中,叶子结点是为 null 的结点;红黑树是一颗二叉平衡树;
红黑树依靠三种自平衡操作
1) **左旋:**以某个结点作为旋转支点,其右子结点变为旋转结点的父结点,右子结点的左子结点变为旋转结点的右子结点,左子结点保持不变;
2) **右旋:**以某个结点作为旋转支点,其左子结点变为旋转结点的父结点,左子结点的右子结点变为旋转结点的左子结点,右子结点保持不变;
3) **变色:**结点的颜色有红变黑或由黑变红;
红黑树插入
插入操作包含两部分:1、查找插入的位置; 2、插入后自平衡;
1) 从根结点出发;
2) 若根结点为空,那么将插入结点作为根结点,结束;
3) 若根结点不为空,那么把根结点作为当前结点;
4) 若当前结点为null,返回当前结点的父结点,结束;
5) 若当前结点key等于插入key,则更新当前结点的值,结束;
6) 若当前结点key小于插入key,把当前结点的左子结点设置为当前结点,重复步骤4;
7) 若当前结点key大于插入key,把当前结点的右子结点设置为当前结点,重复步骤4;
新插入结点颜色为红色,若插入成功则需做自平衡,自平衡有以下场景:
首先约定如下:
I :插入结点;
P :插入结点的父结点;
S :插入结点的父结点的兄弟结点;
PP :插入结点的父结点的父结点(祖父结点);
1) 红黑树为空树,根结点为null:
处理:
把新插入结点(I)作为根结点,并把结点设置为黑色;
2) 插入结点的key已存在:
处理:
因红黑树总保存平衡,插入前红黑树已经是平衡的,所以不需要做自平衡处理,直接更新结点的 data;
3) 插入结点的父结点(P)为黑色:
处理:
由于新插入的结点是红色的,插入结点的父结点为黑色,直接插入即可,无需做自平衡处理;
4) 插入结点的父结点(P)为红色:
如果插入的父结点(P)为红结点,那么该父结点不可能为根结点,所以插入结点总是存在祖父结点(PP);
4.1):S存在并且为红色:
处理:
将P和S设置为黑色,将PP设置为红色;
若PP为根结点,则将PP重置为黑色,结束;
若PP的父结点存在且为黑色,结束;
若PP的父结点存在且为红色,则把PP设置为插入结点(P),循环步骤4.1,直到满足条件结束;
4.2):S不存在或为黑色,且P是PP的左孩子时:
4.2.1)插入结点(I)是P的左子结点时
处理:
将P设置为黑色,将PP设置为红色,对PP进行右旋
4.2.2)插入结点(I)是P的右子结点时
处理:
对P进行左旋,把P设置为插入结点,得到情景**4.2.1**,进行情景**4.2.1**处理
4.3):S不存在或为黑色,且P是PP的右孩子时:
4.3.1)插入结点(I)是其父结点的右子结点
处理:
将P设置为黑色,将PP设置为红色,对PP进行左旋
4.3.2)插入结点(I)是P的左子结点时
处理:
对P进行右旋,把P设置为插入结点,得到情景**4.3.1**,进行情景**4.3.1**处理
4、红黑树查找
红黑树是一颗二叉平衡树,并且查找不会破坏树的平衡,查找跟二叉平衡树的查找无异。
1) 从根结点出发,把根结点设置为当前结点;
2) 若当前结点为空,返回 null;
3) 若当前结点不为空,用当前结点的key跟查找key作比较;
4) 若当前结点key等于查找key,那么该key就是查找目标,返回当前结点;
5) 若当前结点key小于查找key,把当前结点的左子结点设置为当前结点,重复步骤2;
6) 若当前结点key大于查找key,把当前结点的右子结点设置为当前结点,重复步骤2;
5、红黑树删除
对于普通二叉排序树,删除结点的情况可以分3种:
1) 叶子结点;
2) 只有左子树或只有右子树的结点;
3) 既有左子树又有右子树的结点;
对于一颗普通二叉树的情况3来说,要删除有两个子结点的结点,首先要找到该结点的后继结点,然后用后继结点替换该结点,最后按情况1或情况2中的方法删除后继结点,所以情况3可以转换成情况1或2;
对于删除结点有两个子结点:
若删除结点有两个子结点,先根据删除结点找到后继结点,用后继结点替换删除结点,此时可以认为删除的是后继结点,若后继结点有右子结点则转换为情景2,若后继结点的右子结点又有两个子结点,则转换为情景3;
为了便于理解,可以先这样假设:我们将后继结点记为y,将删除结点记为z,将后继结点的右子结点记为x(可能为空);
将y与z的数据交换,但颜色不交换。这样,实际相当于将删除转移到了y结点,而z结点处保持原先状态(处于平衡),此时可以完全不用理会z结点,直接删除y结点即可,因为y最多只有一个右子树(无左子树)。若x存在且有两个子结点,则转换为情景3继续循环查找后继结点、替换;对于前驱结点处理亦是如此;
对于红黑树来讲,实际上删除的情况只有两种:
1) 单个的叶子结点(非NIL结点);
2) 只有左子树或只有右子树的结点;
根据红黑树的性质,首先要明确在红黑树中不可能出现的组合:
1) 黑结点只有一个黑结点(黑黑)
2) 红结点只有一个黑结点(红黑)
3) 红结点有一个红结点(红红)
删除情景1:单个的叶子结点(非NIL结点)
1)若叶子结点为红色,则直接删除,不影响平衡;
2) 删除的红色结点只有左子树或只有右子树(红黑树中根本不存在这种情况);
3) 删除的结点为黑色(红黑树删除中最复杂的场景,需要做自平衡):
3.1):删除的黑色结点只有左子树或者只有右子树(否则需要继续向下查找):
去掉前面分析过的不存在的情况,这种情况下结点的结构只能是黑红;
处理:
即用删除结点的右子树(或左子树)替换删除结点,将删除结点的右子树(或左子树)设置为黑色;
3.2):删除结点为黑色结点(且没有孩子结点):
首先约定如下:
D:待删除结点
P:待删除结点的父结点
S:待删除结点的兄弟结点
SL:待删除结点的兄弟结点的左子结点
SR:待删除结点的兄弟结点的右子结点
3.2.1):
D是P的左子结点, 且S是红色
处理:
将P和S的颜色互换(P变成红色,S变成黑色),对P进行左旋,得到情景**3.2.4**,继续情景**3.2.4**处理
D是P的右子结点,且S是红色
处理:
将P和S的颜色互换(P变成红色,S变成黑色),对P进行右旋,得到情景**3.2.4**,继续情景**3.2.4**处理
3.2.2):
D是P的左子结点,且S是黑色,SR是红色
处理:
将P和S的颜色互换(S变成P的颜色,P变成黑色),将SR变成黑色,对P进行左旋,删除D
D是P的右子结点,且S是黑色,SL是红色
处理:
将P和S的颜色互换(S变成P的颜色,P变成黑色),将SL变成黑色,对P进行右旋,删除D
3.2.3):
D是P的左子结点,且S是黑色,SR是黑色,SL是红色
处理:
将S变成红色,将SL变成黑色,对S进行右旋,得到情景**3.2.2**,继续情景**3.2.2**的处理
D是P的右子结点,且S是黑色,SL是黑色,SR是红色
处理:
将S变成红色,将SR变成黑色,对S进行左旋,得到情景**3.2.2**,继续情景**3.2.2**的处理
3.2.4):
D是P的左子结点(或右子结点),且S是黑色,SR是黑色,SL是黑色
处理:
将S变成红色,把P作为新的替换结点。
删除D后需要重新进行删除结点情景处理。
这句话的意思是把P当成D(只是不要删除P了),再看是以上哪种情况,再进行对应的调整,这样一直向上,直到新的起始点为根结点。
3.2.5):
P是红色,S是黑色,SL是黑色,SR是黑色
处理:
将P变成黑色,将S变成红色,删除D
参考:
https://www.jianshu.com/p/e13...
https://www.jianshu.com/p/717...
https://baijiahao.baidu.com/s...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。