浅谈Java二叉树

来源:互联网 发布:网络销售与网络推广 编辑:程序博客网 时间:2024/06/06 08:44

一、树的优点:

1.      像链表一样快速的插入和删除。

2.      像有序数组一样快速查找。

二、二叉树概念

1.      路径:一个节点到另一个节点,所经过的节点顺序排列后,就是“路径”。

2.      根:一个树只有一个“根”,也就是树的入口节点。

3.      父节点:每个节点只能有一个父节点。

4.      子节点:每个节点的子节点数目可以是0、1、2,最少0个,最多两个。

5.      叶节点:没有子节点的节点称为“页节点”,这个节点可能是树的最后一层。

6.      子树:每个节点都可以是“子树”的根,它和它所有的子节点构成了“子树”。

7.      层:假设根节点是0层,它的子节点就是1层,依次类推。

三、二叉树的特性

1.      在二叉树的第k层上,最多有2k-1 个结点。

2.        深度为m的二叉树最多有个2m-1个结点。

3.        在任意一棵二叉树中,度数为0的结点(即叶子结点)总比度为2的结点多一个。

4.       具有n个结点的二叉树,其深度至少为[log2n]+1

四、时间复杂度

O(logN)

五、代码

代码有三个类:Node.java(树的节点)BinaryTree.java(二叉树)BinaryTreeApp.java(测试类,包含main方法)

代码清单:

1.  Node.java(树的节点)



package org.fizz.ocup.dataStructure.tree.binaryTree;/** * 树的节点 * @author zz * */public class Node {public int id;public double data;public Node leftNode;public Node rightNode;public void dispalyNode(){System.out.print("{" + id +", " + data + "} ");}}

2.      BinaryTree.java(二叉树)

package org.fizz.ocup.dataStructure.tree.binaryTree;import java.util.Stack;/** * 二叉树 * @author zz * */public class BinaryTree {private Node root;/** * 查找并返回id相同的node,若未找到返回null * @param id * @return Node */public Node find(int id){Node current = root;while(current.id != id){if(current.id < id){//当前节点的id小于查找的id,则去右边找,反之去左边找current = current.rightNode;}else{current = current.leftNode;}if(current == null){//如果current为空,说明没有找到id相同的数据项,返回空return null;}}return current;}/** * 插入一个节点 * @param id * @param data */public void insert(int id, double data){Node newNode = new Node();newNode.id = id;newNode.data = data;if(root == null){root = newNode;}else{Node current = root;Node parent;while(true){parent = current;if(id < current.id){current = current.leftNode;if(current == null){parent.leftNode = newNode;return;}}else{current = current.rightNode;if(current == null){parent.rightNode = newNode;return;}}}}}/** * 根据id删除一个节点 * @param id * @return boolean */public boolean delete(int id){Node current = root;Node parent = root;boolean isLeftNode = false;while(current.id != id){parent = current;if(id < current.id){isLeftNode = true;current = current.leftNode;}else{isLeftNode = false;current = current.rightNode;}if(current == null){//未找到,直接返回nullreturn false;}}//以上为:找到要删除的节点//current 是当前节点(也就是要删除的节点)if(current.leftNode == null && current.rightNode == null){//如果current没有子节点的情况if(current == root){root = null;}else if(isLeftNode){parent.leftNode = null;}else{parent.rightNode = null;}}else if(current.leftNode == null){//current 左子节点为空,右子节点不为空if(current == root){root = current.rightNode;}else if(isLeftNode){parent.leftNode = current.rightNode;}else{parent.rightNode = current.rightNode;}}else if(current.rightNode == null){//current 右子节点为空,左子节点不为空if(current == root){root = current.leftNode;}else if(isLeftNode){parent.leftNode = current.leftNode;}else{parent.rightNode = current.leftNode;}}else{//current 左和右子节点都不为空Node delNode = current;Node successor = getSuccessor(delNode);if(current == root){root = successor;}else if(isLeftNode){parent.leftNode = successor;}else{parent.rightNode = successor;}successor.leftNode = delNode.leftNode;}return true;}/** * 获得将要删除的节点的继承者节点</br> * 默认将该节点的右子节点的最左端节点 作为该节点的继承者 * @param delNode * @return Node */private Node getSuccessor(Node delNode){Node successorParent = delNode;//继承者的父级Node successor = delNode;//继承者Node current = delNode.rightNode;//从该节点的右子节点开始找其最左端的子节点while(current != null){successorParent = successor;successor = current;current = current.leftNode;}if(successor != delNode.rightNode){//如果不是该节点的直接右子节点,则做连接successorParent.leftNode = successor.rightNode;successor.rightNode = delNode.rightNode;}return successor;}/** * 遍历树 * @param traverseType */public void traverse(int traverseType){switch(traverseType){case 1: System.out.println("前序遍历:");preorder(root);break;case 2: System.out.println("中序遍历:");inorder(root);break;case 3: System.out.println("后序遍历:");postorder(root);break;}}/** * 前序遍历 * @param localRoot */private void preorder(Node localRoot){if(localRoot != null){System.out.print(localRoot.data + " ");preorder(localRoot.leftNode);preorder(localRoot.rightNode);}}/** * 中序遍历 * @param localRoot */private void inorder(Node localRoot){if(localRoot != null){inorder(localRoot.leftNode);System.out.print(localRoot.data + " ");inorder(localRoot.rightNode);}}/** * 后序遍历 * @param localRoot */private void postorder(Node localRoot){if(localRoot != null){postorder(localRoot.leftNode);postorder(localRoot.rightNode);System.out.print(localRoot.data + " ");}}/** * 显示树的内容 */public void displayTree(){Stack<Node> globalStack = new Stack<Node>();globalStack.push(root);int nBlanks = 32;boolean isRowEmpty = false;System.out.println("...................................................");while(isRowEmpty == false){Stack<Node> localStack = new Stack<Node>();isRowEmpty = true;for(int j=0;j<nBlanks;j++){System.out.print(" ");}while(globalStack.isEmpty() == false){Node temp = globalStack.pop();if(temp != null){System.out.print(temp.id);localStack.push(temp.leftNode);localStack.push(temp.rightNode);if(temp.leftNode != null || temp.rightNode != 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("................................................................");}}


3.      BinaryTreeApp.java(测试类,包含main方法)

package org.fizz.ocup.dataStructure.tree.binaryTree;import java.io.BufferedReader;import java.io.InputStreamReader;public class BinaryTreeApp {public static void main(String[] args) throws Exception {int value;BinaryTree bt = new BinaryTree();bt.insert(66, 6.2);bt.insert(99, 9.2);bt.insert(22, 2.2);bt.insert(00, 0.2);bt.insert(33, 3.2);bt.insert(44, 4.2);bt.insert(11, 1.1);bt.insert(77, 7.2);bt.insert(55, 5.2);bt.insert(88, 8.2);while(true){System.out.print("Enter first letter of show, ");System.out.print("insert,find,delete,or traverse: ");int choice = getChar();switch(choice){case 's':bt.displayTree();break;case 'i':System.out.print("Enter value to insert: ");value = getInt();bt.insert(value, value + 0.9);break;case 'f':System.out.print("Enter value to find: ");value = getInt();Node found = bt.find(value);if(found != null){System.out.print("Found: ");found.dispalyNode();System.out.println();}else{System.out.println("Could not find " + value );}break;case 'd':System.out.print("Enter value to delete: ");value = getInt();boolean didDelete = bt.delete(value);if(didDelete){System.out.println("Deleted " + value);}else{System.out.println("Could not delete " + value);}break;case 't':System.out.println("Enter type 1,2 or 3: ");value = getInt();bt.traverse(value);break;default:System.out.println("Invalid entyr");}}}private static String getString() throws Exception{InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);String s = br.readLine();return s;}private static int getChar() throws Exception{String s = getString();return s.charAt(0);}public static int getInt() throws Exception{String s = getString();return Integer.parseInt(s);}}

六、数组的详细操作代码在:

1.   github地址:https://github.com/oszz/ocup.git

2.   1.0版本中,包目录为:org.fizz.ocup.dataStructure.tree.binaryTree




1 0