树的主要算法有插入,查找,显示,遍历,删除,其中显示和删除略微复杂。

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树的更多相关文章

  1. Java数据结构和算法(七)--AVL树

    在上篇博客中,学习了二分搜索树:Java数据结构和算法(六)--二叉树,但是二分搜索树本身存在一个问题: 如果现在插入的数据为1,2,3,4,5,6,这样有序的数据,或者是逆序 这种情况下的二分搜索树 ...

  2. Java数据结构和算法 - 什么是2-3-4树

    Q1: 什么是2-3-4树? A1: 在介绍2-3-4树之前,我们先说明二叉树和多叉树的概念. 二叉树:每个节点有一个数据项,最多有两个子节点. 多叉树:(multiway tree)允许每个节点有更 ...

  3. Java数据结构和算法(七)B+ 树

    Java数据结构和算法(七)B+ 树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 我们都知道二叉查找树的查找的时间复杂度是 ...

  4. Java数据结构和算法(一)树

    Java数据结构和算法(一)树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 前面讲到的链表.栈和队列都是一对一的线性结构, ...

  5. Java数据结构和算法(四)赫夫曼树

    Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ...

  6. java数据结构和算法07(2-3-4树)

    上一篇我们大概了解了红黑树到底是个什么鬼,这篇我们可以看看另外一种树-----2-3-4树,看这个树的名字就觉得很奇怪.... 我们首先要知道这里的2.3.4指的是任意一个节点拥有的子节点个数,所以我 ...

  7. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

  8. Java数据结构和算法 - 递归

    三角数字 Q: 什么是三角数字? A: 据说一群在毕达哥拉斯领导下工作的古希腊的数学家,发现了在数学序列1,3,6,10,15,21,……中有一种奇特的联系.这个数列中的第N项是由第N-1项加N得到的 ...

  9. Java数据结构与算法 - 外部存储

    Q: 什么是外部存储? A: 外部存储特指某类磁盘系统,例如在大多数台式电脑或服务器中的硬盘. Q: 如何访问外部存储? A: 我们所学的数据结构都是假设数据存储在内存中,但是,在很多情况下要处理的数 ...

随机推荐

  1. C++实现堆排序

    堆排序是合并排序和插入排序排序方法共同的长处.它的时间复杂度O(nlgn),这也是一个地方排序算法:在任何时候,外阵中拥有唯一不变的输入数组存储的元素.引进第一家引进什么样的堆堆. 1.建堆:堆数据结 ...

  2. 联想A798T刷机包 基于百度云V6 集成RE3.1.7美化版 精简冗余文件

    ROM介绍 1.apk进行odex合并及zipaliang优化-省电及降低内存暂用. 2.測试相机.通话.数据.wifi.蓝牙.等传感器均正常,. 3.提供时间居中防iphone状态栏补丁 4.增加I ...

  3. DocFX

    微软开源全新的文档生成工具DocFX 微软放弃Sandcastle有些年头了,微软最近开源了全新的文档生成工具DocFX,目前支持C#和VB,类似JSDoc或Sphinx,可以从源代码中提取注释生成文 ...

  4. Asp.NET MVC3 使用 SignalR 实现推(持续)

    一,Persistent Connection 演示示例教程 1.实现server端代码 1),编写server PersistentConnection 代码 项目中 SignalR 文件夹下创建 ...

  5. HDU 1698 Just a Hook (段树更新间隔)

    Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing for m ...

  6. Cocos2d-x场景变化相关功能介绍

    现场由导演级交换机Director实现.之间的相关的功能,如下面: runWithScene(Scene* scene).该函数能够执行场景.仅仅能在启动第一个场景时候调用该函数.假设已经有一个场景执 ...

  7. phonegap+emberjs+python手机店发展,html5实现本地车类别~

    商城开发项目,现在需要做出APP,无奈出场前android但不是很精通.最后选择phonegap实现app. 由于之前办理购物车分为登陆和登陆后两种情况,登录前必须充分利用本地存储.而基于phoneg ...

  8. 【Android进阶】获取Android软件的版本信息

    PackageInfo pinfo = getPackageManager().getPackageInfo("com.andbase", PackageManager.GET_C ...

  9. Linux高性能server规划——处理池和线程池

    进程池和线程池 池的概念 由于server的硬件资源"充裕".那么提高server性能的一个非常直接的方法就是以空间换时间.即"浪费"server的硬件资源.以 ...

  10. 图片切割工具---产生多个div切割图片 采用for和一的二维阵列设置背景位置

    照片库 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb21vZ2c=/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...