存储方式
一般使用数组、链表来存储树(节点)。链表的优点就是添加、删除。数组优点是访问(遍历)。
一维数组表示法
首先将二叉树当作一颗满二叉树(Full Binary Tree),因此第K层具有2k-1 个节点。按照规则存放在一维数组中。
原理
- 对于一个具有n个节点的二叉树,可以使用一个长度为2n的数组来表示它。通常,数组的索引从0开始。 对于数组中的任意索引 i,如果 i 处的元素表示二叉树的一个节点,那么:
- 节点i的左子节点将位于索引 2i + 1的位置。
- 节点i的右子节点将位于索引 2i + 2的位置。
- 节点i的父节点将位于索引 (i - 1) / 2的位置(如果i不是根节点)。
最佳实践
-
在数组中表示二叉树时,确保数组的大小足够以容纳树中的所有节点。通常情况下,您需要知道树的大小(节点数)以便创建正确大小的数组。
-
当使用数组表示树时,树的结构通常是静态的,即不支持插入或删除节点。如果需要经常进行插入和删除操作,使用链表表示法可能更合适。
-
当数组表示的二叉树是满二叉树时(每个层级都是满的),效果最好。如果树是完全二叉树,效果也不错,但如果树的形状不规则,可能会浪费一些空间。
示例
public class ArrayBinaryTree { private int[] treeArray; public ArrayBinaryTree(int size) { treeArray = new int[size]; } public int find(int value) { for (int i = 0; i < treeArray.length; i++) { if (treeArray[i] == value) { return i; } } return -1; } public void insert(int value) { for (int i = 0; i < treeArray.length; i++) { if (treeArray[i] == 0) { treeArray[i] = value; return; } } } public void preOrderTraversal(int index) { if (index >= treeArray.length || treeArray[index] == 0) { return; } System.out.print(treeArray[index] + " "); preOrderTraversal(2 * index + 1); // 左子节点 preOrderTraversal(2 * index + 2); // 右子节点 } public static void main(String[] args) { // 构建数组其实就是构建树(数组索引与树的左右子节点、父节点有关系) ArrayBinaryTree tree = new ArrayBinaryTree(10); tree.insert(1); tree.insert(2); tree.insert(3); tree.insert(4); tree.insert(5); // 打印树结构,元素为0的表示是空节点即不存在的节点(空间浪费哦) System.out.println("Tree structure:"); for (int value : tree.treeArray) { System.out.print(value + " "); } // 查找元素 System.out.println("\nFind value 3 at index: " + tree.find(3)); // 前序排序 System.out.println("Pre-order traversal:"); tree.preOrderTraversal(0); } }
输出:
Tree structure: 1 2 3 4 5 0 0 0 0 0 Find value 3 at index: 2 Pre-order traversal: 1 2 4 5 3
