顺序存储二叉树
从数据存储来看,数组存储方式和树的存储方式可以相互转化,数组可以转化成树,树也可以转化成数组。
顺序存储二叉树的特点:
- 顺序二叉树通常只考虑完全二叉树。
- 第n个元素的左子节点 2 * n + 1
- 第n个元素的右子节点 2 * n + 2
- 第n个元素的父节点为 (n-1) / 2
- n :表示二叉树中的第几个元素(按0开始编号)
代码实现前序遍历(数组形式):
//index 代表下标 默认0
public void preOrder(int index){
if (arr.length == 0){
System.out.println("数组为空");
}
System.out.println(arr[index]);
//左递归
if (index * 2 + 1 < arr.length)
preOrder(index *2 +1 );
//右递归
if (index * 2 + 2 < arr.length)
preOrder(index * 2 +2);
}
1
2
4
5
3
6
7
线索化二叉树
二叉树可以使用两种存储结构:顺序存储和二叉链表。在使用二叉链表的存储结构的过程中,会存在大量的空指针域,为了充分利用这些空指针域,引申出了“线索二叉树”。
-
n个节点的二叉链表含有n+1个空指针域。利用二叉链表中的空指针域存放该节点在某种遍历次序下的前驱和后继节点指针。
-
这种加上线索的二叉链表成为线索链表,相应的二叉树成为线索二叉树,根据线索性质的不同,线索二叉树可分为前序线索二叉树, 中序线索二叉树和后序线索二叉树。
-
一个节点的前一个节点,称为前驱节点。
-
一个节点的后一个节点, 称为后续节点。
代码实现 中序二叉树:
思路:
-
left 指的可能是左子树也可能是前驱节点。因此要设置一个变量来判断其为左子树还是前驱节点。right同理。
-
当前节点的左指针指向前驱节点, 前驱节点的右指针指向当前节点。
//中序线索化二叉树
public void threadInfixTree(Node node){
if(node == null)
return;
//处理左子树
threadInfixTree(node.getLeft());
//线索化当前节点
//处理前驱节点 : 当前节点的左指针指向前驱节点
if (node.getLeft() == null){
node.setLeft(pre);
node.setLeftThread(true);
}
//处理后续节点: 前驱节点的右指针指向当前节点
if (pre != null && pre.getRight() == null){
pre.setRight(node);
pre.setRightThread(true);
}
// 将此节点作为下一次的前序节点.
pre = node;
// 处理右子树
threadInfixTree(node.getRight());
}
遍历中序线索化二叉树:
思路:
- 找到 isLeftThread == true的点。
- 最先找到的是最左子树点,打印当前节点。
- 如果当前节点的右指针是后续节点 isRightThread = =true 就一直输出
- 替换遍历的点
//遍历
public void threadList(){
Node node = root;
while (node !=null){
//循环找到isLeftThread = true 的节点 第一个为D,第二个为F
while (!node.isLeftThread()){//左指针为左子树 而非前驱节点
node = node.getLeft();
}
//打印当前节点
System.out.println(node);
//如果当前节点的右节点是后续节点那么就一种输出
while (node.isRightThread()){
node = node.getRight();
System.out.println(node);
}
//替换遍历的点
node = node.getRight();
}
}