仅用常数空间实现对一棵二叉树的遍历。
寻找当前节点的前驱节点,判断前驱节点的右节点是否为当前节点,若否则证明还未遍历左子树,将前驱节点的右节点指向当前节点,若是则证明当前节点的左子树全部遍历完成。
- 前序遍历
- 新建一个当前节点指向 root 节点;
- 如果当前节点的左节点为空,输出当前节点,并将其右节点置为新的当前节点;
- 如果当前节点的左节点非空,寻找当前节点的前驱节点:
- 如果前驱节点的右节点为空,将其指向当前节点,输出当前节点,并将当前节点的左节点置为新的当前节点;
- 如果前驱节点的右节点非空(意味着前驱节点的右节点为当前节点,当前节点的左子树已经全部遍历完成),将其右节点置空(还原二叉树),并将当前节点的右节点置为新的当前节点。
- 重复步骤 2-3 至当前节点为空。
- 中序遍历
- 新建一个当前节点指向 root 节点;
- 如果当前节点的左节点为空,输出当前节点,并将其右节点置为新的当前节点;
- 如果当前节点的左节点非空,寻找当前节点的前驱节点:
- 如果前驱节点的右节点为空,将其指向当前节点,并将当前节点的左节点置为新的当前节点;
- 如果前驱节点的右节点非空,将其右节点置空,输出当前节点,并将当前节点的右节点置为新的当前节点。
- 重复步骤 2-3 至当前节点为空。
- 后序遍历
- 新建一个临时节点,并令该节点的左节点指向 root 节点;
- 如果当前节点的左节点为空,将其右节点置为新的当前节点;
- 如果当前节点的左节点非空,寻找当前节点的前驱节点:
- 如果前驱节点的右节点为空,将其指向当前节点,并将当前节点的左节点置为新的当前节点;
- 如果前驱节点的右节点非空,倒序输出当前节点左节点到前驱节点,将前驱节点的右节点置空,并将当前节点的右节点置为新的当前节点。
- 重复步骤 2-3 至当前节点为空。
- 节点分为红色或者黑色;
- 根节点必为黑色;
- 叶子节点都为黑色,且为null;
- 连接红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点);
- 从任意节点出发,到其每个叶子节点的路径中包含相同数量的黑色节点;
- 新加入到红黑树的节点为红色节点。
- 不加黑色节点的原因:从根节点到叶子节点的黑色节点数相同,加入黑色节点必定会破坏性质。
- 从根节点到叶子节点的最长路径不大于最短路径的2倍。
- 最长路径为红黑节点交替的路径,最短路径为全黑节点路径。
- 左旋:将根节点作为新左节点,右节点作为新根,右节点的左节点作为新左节点的右节点。
- 右旋:将根节点作为新右节点,左节点作为新根,左节点的右节点作为新右节点的左节点。
- 无需调整
- 当父节点为黑色节点时。
- 变色
- 空树插入(将根节点变黑);
- 父节点和叔父节点都为红色。
- 旋转 + 变色(父节点为红,叔父节点为黑)
- 父节点为左节点
- 插入节点为左节点:右旋父节点
- 插入节点为右节点:左旋父节点,右旋祖父节点
- 父节点为右节点
- 插入节点为右节点:左旋父节点
- 插入节点为左节点:右旋父节点,左旋祖父节点
- 统一的变色操作:将旋转后的树的根节点变为黑色(为了不破坏上层树的性质),其子节点变为红色。
- 父节点为左节点
- 删除的是根节点,则直接将根节点置为 null;
- 待删除节点的左右子节点都为 null,删除时将该节点置为 null;
- 待删除节点的左右子节点有一个有值,则用有值的节点替换该节点即可;
- 待删除节点的左右子节点都不为 null,则找前驱或者后继,将前驱或者后继的值复制到该节点中,然后删除前驱或者后继;
- 节点删除后可能会造成红黑树的不平衡,需通过变色和旋转来调整。