/**
* 概念介绍:
*
* 树:树由边连接的节点构成。
* 多路树:节点可以多于两个。
* 路径:顺着连接点的边从一个节点到另一个节点,所以过的节点顺序排列就称做路径。
* 根:树的顶端节点称为根。
* 父节点:每个节点都有一条边向上连接到另一个节点,这个节点就称为父节点。
* 子节点:每个节点都可能有一条或多条边向下连接其它节点,下面这些节点就称为子节点。
* 叶节点:没有子节点的节点为叶子节点或叶节点。
* 子树:每个节点都可以作为子树的根,它和它所有的子节点都包含在子树中。
* 访问:当程序控制流程到达某个节点时,就称为“访问”这个节点。
* 遍历:遍历树意味着要遵循某种特定的顺序访问树中所有的节点。
* 层:一个节点的层数是指从根开始到这个节点有多少“代”。一般根为第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):
*/
/**
* 总结:
* 树结合了数组和链表的优点,是一种非常高效的数据结构。
*/