数据结构之树(二叉树的存储方式之数组)
1.算法衡量优劣之时间复杂度2.数据结构与算法之概念3.算法衡量优劣之空间复杂度4.数据结构之数组5.数据结构之链表6.数据结构之栈7.N-皇后问题8.算术表达式的表示法(即求值法)9.算术表达式求值法(表达式求值)之前序表示法求值10.算术表达式求值法(表达式求值)之后序表示法求值11.数据结构之队列(一般队列)12.数据结构之队列(循环队列)13.数据结构之队列(双向队列)14.数据结构之树(基本概念)15.数据结构之树(二叉树)16.数据结构之树(Huffman tree(赫夫曼树 / 霍夫曼树 / 哈夫曼树 / 最优二叉树))
17.数据结构之树(二叉树的存储方式之数组)
18.数据结构之树(二叉树的存储方式之链表)19.数据结构之树(遍历)20.数据结构之树(二叉运算树)21.数据结构之树(二叉搜索树)22.数据结构之树(线索树)23.数据结构之树(树转化为二叉树也叫二叉化)24.确定唯一二叉树存储方式
一般使用数组、链表来存储树(节点)。链表的优点就是添加、删除。数组优点是访问(遍历)。
一维数组表示法
首先将二叉树当作一颗满二叉树(Full Binary Tree),因此第K层具有2k-1 个节点。按照规则存放在一维数组中。
原理
- 对于一个具有n个节点的二叉树,可以使用一个长度为2n的数组来表示它。通常,数组的索引从0开始。 对于数组中的任意索引 i,如果 i 处的元素表示二叉树的一个节点,那么:
- 节点i的左子节点将位于索引 2i + 1的位置。
- 节点i的右子节点将位于索引 2i + 2的位置。
- 节点i的父节点将位于索引 (i - 1) / 2的位置(如果i不是根节点)。
最佳实践
-
在数组中表示二叉树时,确保数组的大小足够以容纳树中的所有节点。通常情况下,您需要知道树的大小(节点数)以便创建正确大小的数组。
-
当使用数组表示树时,树的结构通常是静态的,即不支持插入或删除节点。如果需要经常进行插入和删除操作,使用链表表示法可能更合适。
-
当数组表示的二叉树是满二叉树时(每个层级都是满的),效果最好。如果树是完全二叉树,效果也不错,但如果树的形状不规则,可能会浪费一些空间。
示例
Java语言
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); } }
输出:
1 2 3 4 5 | 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 |
python语言实现
1 class BinaryTree: 2 def __init__(self, size): 3 self.tree = [None] * size 4 5 ''' 6 1. 先根节点 0 7 2. 左子节点 2 * 0 + 1 8 3. 右子节点 2 * 0 + 2 9 4. 把第2步的左子节点当作根节点,插入其左、右子节点 10 5. 其左子节点 2 * 1 + 1 11 6. 其右子节点 2 * 2 + 2 12 7. 然后继续按此规律处理即把第5步的左子节点当作根节点继续处理 13 ''' 14 15 def insert(self, value): 16 for i in range(len(self.tree)): 17 if self.tree[i] is None: 18 self.tree[i] = value 19 return 20 21 # 前序遍历: 根节点在左右子树所有节点前面即第1个。然后左子树(当作独立的树)进行处理,左子树遍历完,右子树遍历 22 def pre_order(self, index): 23 if index >= len(self.tree) or self.tree[index] is None: 24 return 25 print(self.tree[index]) 26 self.pre_order(2 * index + 1) 27 self.pre_order(2 * index + 2) 28 29 # 中序遍历: 根节点在左右子树的中间(不停的分独立树,直到无法再分为止,然后访问左子树节点(只有1个节点)、其根节点、右子树节点(也是不停分)) 30 def in_order(self, index): 31 if index >= len(self.tree) or self.tree[index] is None: 32 return 33 self.in_order(2 * index + 1) 34 print(self.tree[index]) 35 self.in_order(2 * index + 2) 36 37 # 后序遍历:道路一样,不停拆树,直到拆不了,就可以处理。处理:左子树节点-->右子树节点-->其根节点 38 def post_order(self, index): 39 if index >= len(self.tree) or self.tree[index] is None: 40 return 41 self.post_order(2 * index + 1) 42 self.post_order(2 * index + 2) 43 print(self.tree[index]) 44 45 46 # 创建一个大小为10的二叉树对象 47 tree = BinaryTree(10) 48 # 插入节点 49 tree.insert(1) 50 tree.insert(2) 51 tree.insert(3) 52 tree.insert(4) 53 tree.insert(5) 54 # 先序遍历 55 print("Pre-order traversal:") 56 tree.pre_order(0) 57 # 中序遍历 58 print("In-order traversal:") 59 tree.in_order(0) 60 # 后序遍历 61 print("Post-order traversal:") 62 tree.post_order(0)
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Pre-order traversal: 1 2 4 5 3 In-order traversal: 4 2 5 1 3 Post-order traversal: 4 5 2 3 1 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏