法一:
给定一个数组a[MAXSIZE],若父结点为a[k] (k != 0),则其左子结点为a[2k],右子结点为a[2k+1],左子结点的左子结点为a[(2^2)*k],左子结点的右子结点为a[(2^2)*k+1],右子结点的左子结点为a[(2^2)*k+2],右子结点的右子结点为a[(2^2)*k+3]......
可以推导出,深度为n的第一个结点的左子结点(位于n+1层)为a[(2^n)*k],另一个子结点即右子结点为a[2^n)*k+1]
那么我们要求出深度为n+1时的任一结点,只要将其数组下标与深度的关系得出即可列出一个等式,令返回值==等式值即可,时间复杂度为O(1)
法二:
通过上图我们发现如果完全二叉树的一个父结点编号为k,那么它左儿子的编号就是2*k,右儿子的编号就是2*k+1。如果已知儿子(左儿子或右儿子)的编号是x,那么它父结点的编号就是x/2,注意这里只取商的整数部分。在C语言中如果除号‘/’两边都是整数的话,那么商也只有整数部分(即自动向下取整),即4/2和5/2都是2。另外如果一棵完全二叉树有N个结点,那么这个完全二叉树的高度为log2 N简写为log N,即最多有log N层结点。
代码实现
public class ArrBinaryTree { private int[]arr;//存储数据 public ArrBinaryTree(int[] arr) { this.arr = arr; } /*顺序存储二叉树*/ /** * * @description:前序遍历 * @params:1.数组下标 * @return: * @author: 苏兴旺 * @time: 2020/3/13 14:25 */ public void preOrder(int index){ if (arr==null || arr.length==0){ System.out.println("数组为空!不能前序遍历"); return; } /*输出当前元素*/ System.out.println(arr[index]); //左递归遍历 if (index*2+1<arr.length){ preOrder(2*index+1); } //右递归遍历 if (index*2+2<arr.length){ preOrder(index*2+2); } } /*中序遍历*/ public void infixOrder(int index){ //左递归 if (index *2+1<arr.length){ infixOrder(index*2+1); } //输出当前节点 System.out.println(arr[index]); //右递归 if (index*2+2<arr.length){ infixOrder(index*2+2); } } /*后序遍历*/ public void postOrder(int index){ //左递归 if (index*2+1<arr.length){ postOrder(index*2+1); } //右递归 if (index*2+2<arr.length){ postOrder(index*2+2); } //当前节点 System.out.println(arr[index]); }
进行测试
public class ArrBinaryTreeDemo { public static void main(String[] args) { int[] arr ={1,2,3,4,5,6,7}; ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr); /* //前序遍历 System.out.println("前序遍历:"); arrBinaryTree.preOrder(0); //中序遍历 System.out.println("中序遍历:"); arrBinaryTree.infixOrder(0); //后序遍历 System.out.println("后序遍历:"); arrBinaryTree.postOrder(0);*/ } }