Java数据结构与算法(20) - ch08树
树的主要算法有插入,查找,显示,遍历,删除,其中显示和删除略微复杂。
- package chap08.tree;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.util.Stack;
- class Node {
- public int iData;
- public double dData;
- public Node leftChild;
- public Node rightChild;
- public void displayNode() {
- System.out.print("{" + iData + ", " + dData + "}");
- }
- }
- class Tree {
- // first node of tree
- private Node root;
- public Tree() {
- root = null;
- }
- /*
- * 查找
- */
- public Node find(int key) {
- // (assumes non-empty tree)
- Node current = root; // start at root
- while (current.iData != key) // while no match,
- {
- if (key < current.iData) {
- current = current.leftChild;
- }
- else {
- current = current.rightChild;
- }
- if (current == null) {
- return null;
- }
- }
- return current; // found it
- }
- /*
- * 插入
- */
- public void insert(int id, double dd) {
- Node newNode = new Node(); // make new node
- newNode.iData = id; // insert data
- newNode.dData = dd;
- if (root == null) { // no node in root
- root = newNode;
- }
- else // root occupied
- {
- Node current = root; // start at root
- Node parent;
- while (true) // (exits internally)
- {
- parent = current;
- if (id < current.iData) {
- current = current.leftChild;
- if (current == null) {
- // insert on left
- parent.leftChild = newNode;
- return;
- }
- }
- else {
- current = current.rightChild;
- if (current == null) {
- // insert on right
- parent.rightChild = newNode;
- return;
- }
- }
- }
- }
- }
- /*
- * 删除
- */
- public boolean delete(int key)
- {
- // (assumes non-empty list)
- Node current = root;
- Node parent = root;
- boolean isLeftChild = true;
- // search for node
- while (current.iData != key)
- {
- parent = current;
- if (key < current.iData) // go left?
- {
- isLeftChild = true;
- current = current.leftChild;
- }
- else
- {
- isLeftChild = false;
- current = current.rightChild;
- }
- if (current == null) // end of the line,
- return false; // didn't find it
- }
- // if no children, simply delete it
- if (current.leftChild == null && current.rightChild == null) {
- if (current == root) {
- root = null;
- }
- else if (isLeftChild) {
- parent.leftChild = null; // disconnect
- }
- else {
- // from parent
- parent.rightChild = null;
- }
- }
- // if no right child, replace with left subtree
- else if (current.rightChild == null) {
- if (current == root) {
- root = current.leftChild;
- }
- else if (isLeftChild) {
- parent.leftChild = current.leftChild;
- }
- else {
- parent.rightChild = current.leftChild;
- }
- }
- // if no left child, replace with right subtree
- else if (current.leftChild == null)
- if (current == root)
- root = current.rightChild;
- else if (isLeftChild)
- parent.leftChild = current.rightChild;
- else
- parent.rightChild = current.rightChild;
- // 有两个孩子,则用中序后继替代
- else
- {
- // get successor of node to delete (current)
- Node successor = getSuccessor(current);
- // connect parent of current to successor instead
- if (current == root) {
- root = successor;
- }
- else if (isLeftChild) {
- parent.leftChild = successor;
- }
- else {
- parent.rightChild = successor;
- }
- // connect successor to current's left child
- successor.leftChild = current.leftChild;
- }
- return true;
- }
- /*
- * 获取后继
- * 返回具有倒数第二高的值的节点
- * 找到右孩子,然后右孩子的左子孙
- */
- private Node getSuccessor(Node delNode) {
- Node successorParent = delNode;
- Node successor = delNode;
- // go to right child
- Node current = delNode.rightChild;
- while (current != null) {
- successorParent = successor;
- successor = current;
- // go to left child
- current = current.leftChild;
- }
- // if successor not right child
- if (successor != delNode.rightChild) {
- // make connections
- successorParent.leftChild = successor.rightChild;
- successor.rightChild = delNode.rightChild;
- }
- return successor;
- }
- public void traverse(int traverseType) {
- switch (traverseType) {
- case 1:
- System.out.print("\nPreorder traversal: ");
- preOrder(root);
- break;
- case 2:
- System.out.print("\nInorder traversal: ");
- inOrder(root);
- break;
- case 3:
- System.out.print("\nPostorder traversal: ");
- postOrder(root);
- break;
- }
- System.out.println();
- }
- /*
- * 先序遍历
- */
- private void preOrder(Node localRoot) {
- if (localRoot != null) {
- System.out.print(localRoot.iData + " ");
- preOrder(localRoot.leftChild);
- preOrder(localRoot.rightChild);
- }
- }
- /*
- * 中序遍历
- */
- private void inOrder(Node localRoot) {
- if (localRoot != null) {
- inOrder(localRoot.leftChild);
- System.out.print(localRoot.iData + " ");
- inOrder(localRoot.rightChild);
- }
- }
- /*
- * 后序遍历
- */
- 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();
- globalStack.push(root);
- // 打印空格的数量
- int nBlanks = 32;
- // 是否为空的标识
- boolean isRowEmpty = false;
- while (isRowEmpty == false) {
- // 本地栈
- Stack localStack = new Stack();
- // 设置标识为空,后边再根据实际情况判断其是否不为空
- 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 - 1; j++) {
- System.out.print(' ');
- }
- }
- System.out.println();
- System.out.println();
- nBlanks /= 2;
- while (localStack.isEmpty() == false) {
- // 将本地栈的节点放入全局栈,进行反序,从而保证先处理左孩子
- globalStack.push(localStack.pop());
- }
- }
- }
- }
- class TreeApp {
- public static void main(String[] args) throws IOException {
- int value;
- Tree theTree = new Tree();
- theTree.insert(50, 1.5);
- theTree.insert(25, 1.2);
- theTree.insert(75, 1.7);
- theTree.insert(12, 1.5);
- theTree.insert(37, 1.2);
- theTree.insert(43, 1.7);
- theTree.insert(30, 1.5);
- theTree.insert(33, 1.2);
- theTree.insert(87, 1.7);
- theTree.insert(93, 1.5);
- while (true) {
- System.out.print("Enter first letter of show, insert, find, delete, or traverse: ");
- int choice = getChar();
- switch (choice) {
- case 's':
- theTree.displayTree();
- break;
- case 'i':
- System.out.print("Enter value to insert: ");
- value = getInt();
- theTree.insert(value, value + 0.9);
- break;
- case 'f':
- System.out.print("Enter value to find: ");
- value = getInt();
- Node found = theTree.find(value);
- if (found != null) {
- System.out.print("Found: ");
- found.displayNode();
- System.out.print("\n");
- }
- else {
- System.out.print("Could not find ");
- }
- System.out.print(value + '\n');
- break;
- case 'd':
- System.out.print("Enter value to delete: ");
- value = getInt();
- boolean didDelete = theTree.delete(value);
- if (didDelete) {
- System.out.print("Deleted " + value + '\n');
- }
- else {
- System.out.print("Could not delete ");
- }
- System.out.print(value + '\n');
- break;
- case 't':
- System.out.print("Enter type 1, 2 or 3: ");
- value = getInt();
- theTree.traverse(value);
- break;
- default:
- System.out.print("Invalid entry\n");
- }
- }
- }
- /*
- * 获取输入
- */
- 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);
- }
- }
Java数据结构与算法(20) - ch08树的更多相关文章
- Java数据结构和算法(七)--AVL树
在上篇博客中,学习了二分搜索树:Java数据结构和算法(六)--二叉树,但是二分搜索树本身存在一个问题: 如果现在插入的数据为1,2,3,4,5,6,这样有序的数据,或者是逆序 这种情况下的二分搜索树 ...
- Java数据结构和算法 - 什么是2-3-4树
Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...
- Java数据结构和算法(七)B+ 树
Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...
- Java数据结构和算法(一)树
Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...
- Java数据结构和算法(四)赫夫曼树
Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...
- java数据结构和算法07(2-3-4树)
上一篇我们大概了解了红黑树到底是个什么鬼,这篇我们可以看看另外一种树-----2-3-4树,看这个树的名字就觉得很奇怪.... 我们首先要知道这里的2.3.4指的是任意一个节点拥有的子节点个数,所以我 ...
- Java数据结构和算法 - 二叉树
前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...
- Java数据结构和算法 - 递归
三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,……中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...
- Java数据结构与算法 - 外部存储
Q: 什么是外部存储? A: 外部存储特指某类磁盘系统,例如在大多数台式电脑或服务器中的硬盘. Q: 如何访问外部存储? A: 我们所学的数据结构都是假设数据存储在内存中,但是,在很多情况下要处理的数 ...
随机推荐
- 采用Java语言如何实现高速文件复制?
今天review代码也看到了"大神"用老方法来实现文件拷贝.今天归结一下使用Java语言怎样实现高速文件复制: 代码1--使用文件通道的方式: import java.io.Fil ...
- cocos2dx环境配置和打包
安装软件准备就绪: vs2012 cocos2d-x-2.2.1 adt-bundle-windows-x86_64-20121030 android-ndk-r9c-windows-x86_64 j ...
- UNITY3D MAC版本号破解
首先,解释一下.是公司做开发建议去购买正版. 之前网上也有非常多人贴出了破解方法,有些也是能够的.可是大多数解说不太具体,在这里贴出相对具体点的教程.本人亲測成功(測试版本Unity4.0.1 mac ...
- CMSIS标准
CMSIS 标准(Cortex Microcontroller Software Interface Standard) ,翻译过来是"ARM Cortex™ 微控制器软件接口标准" ...
- IOS开发——手动设置屏幕旋转
在移动开发过程.您可能需要跨越看看你的手机.有可能是所有的接口必须跨越,有可能是一个交叉通过电话,当用户当,你的接口也希望他能跨越.还有可能的是,界面的一部分需要被侧向显示.视情况而定,有不同的方法来 ...
- PowerShell 批量导入/导出Active Directory
PowerShell 批量导入/导出Active Directory 近期由于公司要求,须要导入20个供应商.20个客户到AD域中,刚開始手动添�了2个供应商,2个客户.可是感觉费时费 ...
- MemoryBarrier,Volatile
使用MemoryBarrier,Volatile进行同步 上一节介绍了使用信号量进行同步,本节主要介绍一些非阻塞同步的方法.本节主要介绍MemoryBarrier,volatile,Interlock ...
- 跨容器Hybrid离线组件方案
关键词:跨容器.Hybrid.离线 摘要:今天主要讨论的是离线组件跨容器方案,想了解在线页面如何跨webview容器,可以看 http://www.cnblogs.com/yexiaochai/p/5 ...
- 如何对 GIT 分支进行规划? (转)
项目背景: 该项目是在2011年11月份使用Asp.net三层帮荷兰某个客户开发的机票预定系统 该客户主要是做中国与欧洲的旅行社业务,特别是最近两年由于中国的发展因此客户也越来越重视机票业务 于是他们 ...
- 一张图让你看清Java集合类(Java集合类的总结)
如今关于Java集合类的文章非常多,可是我近期看到一个非常有意思图片,基本上把Java集合的整体框架都给展现出来了.非常直观. watermark/2/text/aHR0cDovL2Jsb2cuY3N ...