数据结构与算法(JAVA篇)之树(一)

2024-05-01 20:38

本文主要是介绍数据结构与算法(JAVA篇)之树(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

 
/*** 概念介绍:** 树:树由边连接的节点构成。* 多路树:节点可以多于两个。* 路径:顺着连接点的边从一个节点到另一个节点,所以过的节点顺序排列就称做路径。* 根:树的顶端节点称为根。* 父节点:每个节点都有一条边向上连接到另一个节点,这个节点就称为父节点。* 子节点:每个节点都可能有一条或多条边向下连接其它节点,下面这些节点就称为子节点。* 叶节点:没有子节点的节点为叶子节点或叶节点。* 子树:每个节点都可以作为子树的根,它和它所有的子节点都包含在子树中。* 访问:当程序控制流程到达某个节点时,就称为“访问”这个节点。* 遍历:遍历树意味着要遵循某种特定的顺序访问树中所有的节点。* 层:一个节点的层数是指从根开始到这个节点有多少“代”。一般根为第0层。* 关键字:对象中通常会有一个数据域被指定为关键字,通常使用这个关键字进行查询等操作。* 二叉树:如果树中每个节点最多只能有两个子节点,这样的特殊的树就是二叉树。* 二叉搜索树:二叉树的一个节点的左子节点的关键字值小于这个节点,右子节点的关键字值大*            于或等于这个父节点。* 平衡树与非平衡树:左子节点与左子节点对称的树为平衡树,否则就是非平衡树。* 完全二叉树:二叉树的最后一层都是叶子结点,其它各层都有左右子树,也叫满二叉树。** 为什么用二叉树:1.二叉树结合了另外两种数据结构的优点:一种是有序数组,另一种是链表。*                在树中查找数据的速度和在有序数组中查找的速度一样快,同时插入的速度*                和删除的速度和链表的速度一样。*                2.在有序数组中插入数据项太慢:用二分查找法可以在有序数据中快速的查找*                特定的值,查找所需时间复杂度为O(logN)。然而插入和删除是非常低效的。*                3.在链表中查找太慢:链表的插入和删除操作都很快,时间复杂度是O(1)。*                然而查找数据项是非常低效的。* 二叉树的效率:时间复杂度为O(logN)。树对所有的数据存储操作都很高效。** 程序介绍:对树的一些常用操作进行了封装,包括查询,插入,删除,遍历二叉树(中序,后序,前序)*          以及以树的方式显示二对树的各个结点。**/
/**** @author SunnyMoon*/import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;/*** 定义树的结点类*/
class Node {public int iData;//关键字public double dData;//数据项public Node leftChild;//左子树public Node rightChild;//右子树public void displayNode() {//输出结点内容System.out.print("【");System.out.print("关键字: "+iData);System.out.print(",");System.out.print("值:"+dData);System.out.print("】");}
}/*** 定义二叉树类*/
class Tree {private Node root;public Tree() {root = null;}/*** 查找* @param key* @return*/public Node find(int key) {Node current = root;while (current.iData != key) {if (key < current.iData) {current = current.leftChild;} else {current = current.rightChild;}if (current == null) {return null;}}return current;}
/*** 插入* @param id* @param dd*/public void insert(int id, double dd) {Node newNode = new Node();newNode.iData = id;newNode.dData = dd;if (root == null) {root = newNode;} else {Node current = root;Node parent;while (true) {parent = current;if (id < current.iData) {current = current.leftChild;if (current == null) {parent.leftChild = newNode;return;}} else {current = current.rightChild;if (current == null) {parent.rightChild = newNode;return;}}}}}/*** 删除* @param key* @return*/public boolean delete(int key) {Node current = root;Node parent = root;boolean isLeftChild = true;while (current.iData != key) {parent = current;if (key < current.iData) {isLeftChild = true;current = current.leftChild;} else {isLeftChild = false;current = current.rightChild;}if (current == null) {return false;}}if (current.leftChild == null && current.rightChild == null) {if (current == root) {root = null;} else if (isLeftChild) {parent.leftChild = null;} else {parent.rightChild = null;}} else if (current.rightChild == null) {if (current == root) {root = current.leftChild;} else if (isLeftChild) {parent.leftChild = current.leftChild;} else {parent.rightChild = current.leftChild;}} else if (current.leftChild == null) {if (current == root) {root = current.rightChild;} else if (isLeftChild) {parent.leftChild = current.rightChild;} else {parent.rightChild = current.rightChild;}} else {Node successor = getSuccessor(current);if (current == root) {root = successor;} else if (isLeftChild) {parent.leftChild = successor;} else {parent.rightChild = successor;}successor.leftChild = current.leftChild;}return true;}
/*** 遍历二叉树* @param traverseType*/public void traverse(int traverseType) {switch (traverseType) {case 1:System.out.print("\n" + "前序遍历(Preorder traversal): ");preOrder(root);break;case 2:System.out.print("\n" + "中序遍历(Inorder traversal): ");inOrder(root);break;case 3:System.out.print("\n" + "后序遍历(Postorder traversal): ");postOrder(root);break;}System.out.println();}
/*** 定义定位到后序结点方法* @param delNode* @return*/private Node getSuccessor(Node delNode) {Node successorParent = delNode;Node successor = delNode;Node current = delNode.rightChild;while (current != null) {successorParent = successor;successor = current;current = current.leftChild;}if (successor != delNode.rightChild) {successorParent.leftChild = successor.rightChild;successor.rightChild = delNode.rightChild;}return successor;}
/*** 前序遍历* @param localRoot*/private void preOrder(Node localRoot) {if (localRoot != null) {System.out.print(localRoot.iData + " ");preOrder(localRoot.leftChild);preOrder(localRoot.rightChild);}}
/*** 中序遍历* @param localRoot*/private void inOrder(Node localRoot) {if (localRoot != null) {inOrder(localRoot.leftChild);System.out.print(localRoot.iData + " ");inOrder(localRoot.rightChild);}}
/*** 后序遍历* @param localRoot*/private void postOrder(Node localRoot) {if (localRoot != null) {postOrder(localRoot.leftChild);postOrder(localRoot.rightChild);System.out.print(localRoot.iData + " ");}}
/*** 把关键字按树型输出* ‘--’表示树中这个位置的结点不存在。*/public void displayTree() {Stack globalStack = new Stack(1000);globalStack.push(root);int nBlanks = 32;boolean isRowEmpty = false;System.out.println("-----------------------------------------------------------------------");while (isRowEmpty == false) {Stack localStack = new Stack(1000);isRowEmpty = true;for (int j = 0; j < nBlanks; j++) {System.out.print(" ");}while (globalStack.isEmpty() == false) {Node temp = (Node) globalStack.pop();if (temp != null) {System.out.print(temp.iData);localStack.push(temp.leftChild);localStack.push(temp.rightChild);if (temp.leftChild != null || temp.rightChild != null) {isRowEmpty = false;}} else {System.out.print("..");localStack.push(null);localStack.push(null);}for (int j = 0; j < nBlanks * 2 - 2; j++) {System.out.print(" ");}}System.out.println();nBlanks /= 2;while (localStack.isEmpty() == false) {globalStack.push(localStack.pop());}}System.out.println("-----------------------------------------------------------------------");}
}/*** 使用的栈* @author Administrator*/
class Stack {private int maxSize;private Object[] stackArray;private int top;public Stack(int s) {maxSize = s;stackArray = new Object[maxSize];top = -1;}public void push(Object p) {stackArray[++top] = p;}public Object pop() {return stackArray[top--];}public Object peek() {return stackArray[top];}boolean isEmpty() {if (top == -1) {return true;} else {return false;}}
}
/*** 主方法* @author Administrator*/
class TreeAaa {public static void main(String[] args) throws IOException {int value;Tree theTree = new Tree();theTree.insert(12, 1.5);theTree.insert(15, 2.4);theTree.insert(22, 5.6);theTree.insert(33, 7.1);theTree.insert(55, 3.3);theTree.insert(26, 8.7);theTree.insert(17, 2.3);theTree.insert(8, 6.9);theTree.insert(6, 8.4);theTree.insert(14, 7.0);theTree.insert(23, 1.8);theTree.insert(38, 2.9);while (true) {System.out.print("输入想执行的操作的英文首字母:");System.out.print("插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): ");int choice = getChar();switch (choice) {case 's':theTree.displayTree();break;case 'i':System.out.print("输入想要插入的值: ");value = getInt();theTree.insert(value, value + 0.9);break;case 'f':System.out.print(("输入想要查找的关键字: "));value = getInt();Node found = theTree.find(value);if (found != null) {System.out.print("成功查找: ");found.displayNode();System.out.print("\n");} else {System.out.print("不存在所查询关键字");}System.out.print("输入的关键字:" + value + "\n");break;case 'd':System.out.print("输入想要删除的关键字: ");value = getInt();boolean didDelete = theTree.delete(value);if (didDelete) {System.out.print("删除的值:" + value + "\n");} else {System.out.print("不能执行删除操作");}System.out.println(value);//System.out.print(value + "\n");break;case 't':System.out.print("输入遍历类型 1, 2 或 3:");value = getInt();theTree.traverse(value);break;default:System.out.println("非法输入");}}}public static String getString() throws IOException {InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);String s = br.readLine();return s;}public static char getChar() throws IOException {String s = getString();return s.charAt(0);}public static int getInt() throws IOException {String s = getString();return Integer.parseInt(s);}/*** 运行结果:* 输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): s*-----------------------------------------------------------------------*                                12*                8                              15*        6              ..              14              22*    ..      ..      ..      ..      ..      ..      17      33*  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  26  55* ........................................................23..38..*-----------------------------------------------------------------------*输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): i*输入想要插入的值: 3*输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse): f*输入想要查找的关键字: 14*成功查找: {14,7.0}*输入的关键字:14*输入想执行的操作的英文首字母:插入(Insert), 查找(Find), 删除(Delete), 遍历(Traverse):*//*** 总结:* 树结合了数组和链表的优点,是一种非常高效的数据结构。*/
 

这篇关于数据结构与算法(JAVA篇)之树(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/952617

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2