浅谈Java二叉树

一、树的优点:

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){//未找到,直接返回null
				return 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值