Java 数据结构_树
来源:互联网 发布:python serial 模块 编辑:程序博客网 时间:2024/06/06 08:30
Java 数据结构_树
本文由 Luzhuo 编写,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/78469973
树
树的基本概念
- 树是结点的有限集合
- 双亲: 根结点A是BCD的
双亲
, 下面的BCD都是A的孩子
- 兄弟: 同一个双亲之间的结点, 互称为
兄弟
, BCD互为兄弟 - 堂兄弟: 双亲在同一层的结点, 互称为
堂兄弟
, EFGHIJKL互为堂兄弟 - 度: 连接他的结点数, A的度为3
- 根结点: 无双亲, 且唯一的结点
- 分支结点(非终端结点): 度不为0的结点, BCD都是分支结点, 也称中间结点(除A外)
- 叶结点(终端结点): 度为0的结点, EFGHIJKL都是叶结点.
- 祖先: 之前所有的结点都是祖先, G的祖先是BA
- 子孙: 之后所有的结点都是子孙, B的子孙是EFG
- 有序树(从左到右不能换顺序), 无序树(可换顺序)
- 深度: 树的最大深度, 这颗树的深度为3
- 森林: 多个独立的树(互不相交)放在一起就是森林
- 二叉树: 每个结点的度最多为2的树
- 树的遍历:
- 用途:压缩软件-赫夫曼树 / 搜索-人机对战
二叉树的实现方式
数组实现方式, 删除指定索引位置的结点时, 不会删除他的所有孩子
链式实现方式, 删除指定结点时, 会删除他的所有孩子
二叉树的数组实现方式
二叉树的数组实现代码
/** * 二叉树(数组的表示方式) * @author Luzhuo * A(0) * B(1) C(2) * D(3) E(4) F(5) G(6) * * |A(0)| B(1)|C(2) | D(3)|E(4) | F(5)|G(6) | ...|... | */public class ArrayTree { // 树的数组表示方式 private Node[] nodes; // 树的指针 private int size; // 数组的大小 public ArrayTree(Node root){ init(1024, root); } public ArrayTree(int size, Node root){ init(size, root); } /** * 创建二叉树<br> * 创建存放结点的数组, 设置该数据结构的容量, 设置根结点 * @param size * @param root */ private void init(int size, Node root){ this.nodes = new Node[size]; this.size = size; // 根结点 this.nodes[0] = root; } /** * 销毁二叉树<br> * 删除存放结点的数组 */ public void destory(){ nodes = null; } /** * 根据索引搜索结点 * @param nodeIndex 索引 * @return 结点 */ public Node serchNode(int nodeIndex){ if(nodeIndex < 0 || nodeIndex >= this.size){ throw new ArrayIndexOutOfBoundsException("索引越界."); } return nodes[nodeIndex]; } /** * 添加结点<br> * 添加在父结点的左边时, 添加到数组的奇数索引位置(1, 3, 5 ...), 添加在父结点的右边时, 添加到数组的偶数索引位置(2, 4, 6 ...) * @param nodeIndex 结点索引(从0开始) * @param direction 左边0还是右边1 * @param node 结点 * @return 是否添加成功 */ public boolean addNode(int nodeIndex, int direction, Node node){ if(nodeIndex < 0 || nodeIndex >= this.size){ throw new ArrayIndexOutOfBoundsException("索引越界."); } if(this.nodes[nodeIndex] == null){ throw new NullPointerException("该结点为空"); } // 若某结点再父节点下标 * 2 + 1 ,则表示该结点在左 // 若某结点再父节点下标 * 2 + 2, 则表示该结点在右 int leftIndex = nodeIndex * 2 + 1; int rightIndex = nodeIndex * 2 + 2; if(direction == 0){ if(leftIndex >= this.size || this.nodes[leftIndex] != null) return false; this.nodes[leftIndex] = node; }else if(direction == 1){ if(rightIndex >= this.size || this.nodes[rightIndex] != null) return false; this.nodes[rightIndex] = node; } return true; } /** * 删除索引<br> * @param nodeIndex * @return 被删除的结点 */ public Node deleteNode(int nodeIndex){ if(nodeIndex < 0 || nodeIndex >= this.size){ throw new ArrayIndexOutOfBoundsException("索引越界."); } if(this.nodes[nodeIndex] == null){ throw new NullPointerException("该结点为空"); } Node tempN = this.nodes[nodeIndex]; this.nodes[nodeIndex] = null; return tempN; } /** * 遍历<br> * 之间从左向右遍历数组. */ public void traverse(){ for(int i = 0; i < this.size; i++){ Node data = this.nodes[i]; if(data != null) System.out.print(data + " "); } }}class Node{ public char data; public Node(char data){ this.data = data; } @Override public String toString() { return String.valueOf(data); }}
数组方式测试代码
public class ArrayTreeTest { public static void main(String[] args) { // 测试 ArrayTree tree = new ArrayTree(new Node('A'));// tree.addNode(0, 0, new Node('B'));// tree.addNode(0, 1, new Node('C'));// tree.addNode(1, 0, new Node('D'));// tree.addNode(1, 1, new Node('E'));// tree.addNode(2, 0, new Node('F'));// tree.addNode(2, 1, new Node('G')); // ↓ 简化 int nodeIndex = -1; for(int i = 0; i < 10; i++){ int direction; if(i%2 == 0){ direction = 0; nodeIndex++; }else{ direction = 1; } tree.addNode(nodeIndex, direction, new Node((char)(66+i))); } tree.traverse(); System.out.println(); System.out.println(tree.serchNode(3)); System.out.println(tree.deleteNode(3)); tree.traverse(); tree.destory(); }}
二叉树的链式实现方式
二叉树的链式实现代码
/** * 二叉树(链式实现方式) * @author Luzhuo * (0) * A(1) B(2) * C(3) D(4) E(5) F(6) * 前序遍历(根左右): 0 1 3 4 2 5 6 * 中序遍历(左根右): 3 1 4 0 5 2 6 * 后序遍历(左右根): 3 4 1 5 6 2 0 */public class LinkedTree { Node_ root; // 根结点 public LinkedTree(){ init(); } /** * 创建链式二叉树<br> * 初始化根结点的数据0, 索引0, 左孩子指针null, 右孩子指针null, 父节点指针null */ private void init(){ root = new Node_(); root.data = 0; root.index = 0; root.lChildNode = null; root.rChildNode = null; root.parentNode = null; } /** * 销毁链式二叉树<br> * 递归删除所有孩子, 并指针重置为null */ public void destory(){ this.root.deleteNode(); this.root = null; } /** * 根据索引寻找结点<br> * 递归查找指定索引位置的结点 * @param nodeindex 索引 * @return 结点 */ public Node_ searchNode(int nodeindex){ return this.root.searchNode(nodeindex); } /** * 添加结点<br> * 找到指定位置的结点, 将新结点添加到该结点的左边 / 右边, 并将该结点的指针交给新结点 * @param nodeindex 索引 * @param direction 左边0或右边1 * @param node 被挂在的结点 * @return 添加成功返回true,否则返回false; */ public boolean addNode(int nodeindex, int direction, Node_ node){ Node_ curN = searchNode(nodeindex); if(curN == null) return false; // 加入到该结点的左边or右边 if(direction == 0){ curN.lChildNode = node; }else if(direction == 1){ curN.rChildNode = node; } // 并该结点的指针交给插入的结点 node.parentNode = curN; return true; } /** * 删除指定索引的结点, 注意删除结点,会将挂在在该结点的所有结点同时删除<br> * 找到指定的结点, 递归删除自己所有的孩子 * @param nodeindex 索引 * @return 被删除的结点, 该结点为空返回null */ public Node_ deleteNode(int nodeindex){ Node_ curN = searchNode(nodeindex); if(curN == null) return null; Node_ tempN = curN; curN.deleteNode(); curN = null; return tempN; } /** * 前序遍历(根左右, 根前) */ public void preorderTraversal(){ this.root.preorderTraversal(); } /** * 中序遍历(左根右, 根中) */ public void inorderTraversal(){ this.root.inorderTraversal(); } /** * 后序遍历(左右根, 根后) */ public void postorderTraversal(){ this.root.postorderTraversal(); }}/** * 结点, 创建必须给index和data赋值 * @author Luzhuo * */class Node_{ public int index; // 索引 public char data; // 数据 public Node_ lChildNode; // 左结点指针 public Node_ rChildNode; // 右结点指针 public Node_ parentNode; // 父结点指针 public Node_(){ } public Node_(int index, char data){ this.index = index; this.data = data; } /** * 根据索引寻找结点 * @param nodeindex 索引 * @return 找到结点返回结点, 否则返回null */ public Node_ searchNode(int nodeindex){ // 是否是自身 if(this.index == nodeindex) return this; Node_ tempN; // 是否是左边的孩子,及其子结点 if(this.lChildNode != null){ if(this.lChildNode.index == nodeindex){ return this.lChildNode; }else{ tempN = this.lChildNode.searchNode(nodeindex); if(tempN != null) return tempN; } } // 是否是右边的孩子,及其子结点 if(this.rChildNode != null){ if(this.rChildNode.index == nodeindex){ return this.rChildNode; }else{ tempN = this.rChildNode.searchNode(nodeindex); if(tempN != null) return tempN; } } return null; } public void deleteNode(){ // 删除自己左右边的所有子结点 if(this.lChildNode != null){ this.lChildNode.deleteNode(); } if(this.rChildNode != null){ this.rChildNode.deleteNode(); } // 删除自己在父结点上的指针 if(this.parentNode != null){ if(this.parentNode.lChildNode == this){ this.parentNode.lChildNode = null; } if(this.parentNode.rChildNode == this){ this.parentNode.rChildNode = null; } } } /** * 前序遍历(根左右)<br> * 每个结点先输出自身(根), 然后递归左结点, 在递归右结点 */ public void preorderTraversal(){ // 根 System.out.println("index: " + this.index + " data: " + data + " === "); // 左 if(this.lChildNode != null) this.lChildNode.preorderTraversal(); // 右 if(this.rChildNode != null) this.rChildNode.preorderTraversal(); } /** * 中序遍历(左根右) */ public void inorderTraversal(){ // 左 if(this.lChildNode != null) this.lChildNode.inorderTraversal(); // 根 System.out.println("index: " + this.index + " data: " + data + " === "); // 右 if(this.rChildNode != null) this.rChildNode.inorderTraversal(); } /** * 后序遍历(左右根) */ public void postorderTraversal(){ // 左 if(this.lChildNode != null) this.lChildNode.postorderTraversal(); // 右 if(this.rChildNode != null) this.rChildNode.postorderTraversal(); // 根 System.out.println("index: " + this.index + " data: " + data + " === "); }}
数组方式测试代码
public class LinkedTreeTest { public static void main(String[] args) { // 测试 /* * (0) * A(1) B(2) * C(3) D(4) E(5) F(6) * 前序遍历(根左右): 0 1 3 4 2 5 6 * 中序遍历(左根右): 3 1 4 0 5 2 6 * 后序遍历(左右根): 3 4 1 5 6 2 0 */ LinkedTree tree = new LinkedTree();// tree.addNode(0, 0, new Node_(1, 'A'));// tree.addNode(0, 1, new Node_(2, 'B'));// tree.addNode(1, 0, new Node_(3, 'C'));// tree.addNode(1, 1, new Node_(4, 'D'));// tree.addNode(2, 0, new Node_(5, 'E'));// tree.addNode(2, 1, new Node_(6, 'F')); // ↓ 简化 int nodeIndex = -1; for(int i = 0; i < 10; i++){ int direction; if(i%2 == 0){ direction = 0; nodeIndex++; }else{ direction = 1; } tree.addNode(nodeIndex, direction, new Node_(i + 1, (char)(65+i))); } tree.preorderTraversal(); System.out.println(); tree.inorderTraversal(); System.out.println(); tree.postorderTraversal(); System.out.println(); System.out.println(tree.deleteNode(3).data); System.out.println(tree.deleteNode(2).data); tree.preorderTraversal(); tree.destory(); }}
阅读全文
0 0
- Java 数据结构_树
- 数据结构_栈、队列和树(Java)
- Java数据结构_栈
- java数据结构_笔记(4)_图
- java学习[2]_数据结构
- Java数据结构_散列
- Java 数据结构_线性表
- 数据结构_树结构
- 数据结构_二叉树
- 数据结构_查找_次优查找树
- 数据结构_二叉索引树_模板
- 数据结构_树形结构_二叉树
- 数据结构_线段树_基础模板
- 【C语言】树_数据结构_练习
- java数据结构_附2_Strategy(…
- 数据结构(java)_数组顺序查找
- 数据结构_二叉查找树
- 19-数据结构_树-存储
- 每天一个linux命令(7):mv命令
- 小米等部分手机机型不弹出对话框问题
- gcc编译时遇到“inline function '***' declared but never defined"问题
- 通过scrapy爬取京东商品
- java SE day15火推
- Java 数据结构_树
- 11月7日笔记
- mybatis中mapUnderscoreToCamelCase自动驼峰命名转换
- 413. Arithmetic Slices
- HashMap加入数据后,会自动根据首字母排序
- react进阶之异常处理机制-error Boundaries
- Python 字典(Dictionary)
- DELL 服务器启动出现NO boot device availabel解决方法
- 大数据浪潮下 你也可以转型大数据工程师!