树的主要算法有插入,查找,显示,遍历,删除,其中显示和删除略微复杂。
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(" Preorder traversal: "); preOrder(root); break; case 2: System.out.print(" Inorder traversal: "); inOrder(root); break; case 3: System.out.print(" Postorder 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(" "); } else { System.out.print("Could not find "); } System.out.print(value + ' '); break; case 'd': System.out.print("Enter value to delete: "); value = getInt(); boolean didDelete = theTree.delete(value); if (didDelete) { System.out.print("Deleted " + value + ' '); } else { System.out.print("Could not delete "); } System.out.print(value + ' '); break; case 't': System.out.print("Enter type 1, 2 or 3: "); value = getInt(); theTree.traverse(value); break; default: System.out.print("Invalid entry "); } } } /* * 获取输入 */ 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); } }