Java实现二叉树

描述:

在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

一棵深度为k,且有2^k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。具有n个节点的完全二叉树的深度为floor(log2n)+1。深度为k的完全二叉树,至少有2k-1个节点,至多有2k-1个节点

 

 

代码:

节点类

public class Node {
	public int value;
	public Node leftChild;
	public Node rightChild;
	
	public Node(int val){
		value = val;
	}
	
	public void display(){
		System.out.println(value);
	}
}

二叉树类

public class BinaryTree {
	public Node root;

	// 增加
	public void insert(int val) {
		Node node = new Node(val);

		if (root == null) {
			root = node;
		} else {
			Node parent = root;
			Node current = root;

			while (true) {
				if (val < current.value) {
					parent = current;
					current = current.leftChild;

					if (current == null) {
						parent.leftChild = node;
						break;
					}
				} else if (val > current.value) {
					parent = current;
					current = current.rightChild;

					if (current == null) {
						parent.rightChild = node;
						break;
					}
				} else {
					System.out.println("出现相同值");
				}
			}
		}
	}

	
	// 查找
	public Node find(int key) {
		Node current = root;
		while (current.value != key) {
			if (key < current.value) {
				current = current.leftChild;
			} else if (key > current.value) {
				current = current.rightChild;
			}
			if (current == null) {
				return null;
			}
		}
		return current;
	}



        //中序遍历
	//*****************递归遍历
	public void inOrderTarverse() {
		
		System.out.print("中序遍历:");
		inOrderTarverse(root);
		System.out.println();
		
	}
	private void inOrderTarverse(Node node) {
		
		if( node == null )
			return;
		
		inOrderTarverse(node.leftChild);
		node.display();
		inOrderTarverse(node.rightChild);
	}
	//****************非递归遍历
	public void inOrderByStack() {
		
		System.out.print("中序非递归遍历:");
		
        Stack<Node> stack = new Stack<Node>();  
        Node current = root;  
        
        while (current != null || !stack.isEmpty()) {  
           
        	while (current != null) {  
                
        		stack.push(current);  
                current = current.leftChild;
                
            }  
              
            if (!stack.isEmpty()) {  
                
            	current = stack.pop();  
                current.display();  
                current = current.rightChild;  
            }
            
        }  
        System.out.println();  
		
	}
	
	
	//先序遍历
	//*************递归遍历
	public void perOrderTarverse() {
		
		System.out.print("先序递归遍历:");
		perOrderTarverse(root);
		System.out.println();
		
	}
	private void perOrderTarverse(Node node) {
		
		if(node == null) {
			return ;	
		}	
		node.display();
		perOrderTarverse(node.leftChild);
		perOrderTarverse(node.rightChild);	
	}
	//*************非递归遍历
	public void preOrderByStack(){		
		Node current = root;
		Stack<Node> stack = new Stack<Node>();		
		while( current != null || ! stack.isEmpty() ){			
			while( current != null ){				
				current.display();
				stack.push(current);
				current = current.leftChild;				
			}			
			if( ! stack.isEmpty() ){				
				current = stack.pop();
				current = current.rightChild;				
			}			
		}		
	}
	
	//后序遍历
	//*******************递归遍历
	public void postOrderTanverse() {		
		System.out.print("后序遍历");
		postOrderTanverse(root);
		System.out.println();
		
	}
	private void postOrderTanverse(Node node) {		
		if(node == null) {		
			return;		
		}		
		postOrderTanverse(node.leftChild);
		postOrderTanverse(node.rightChild);
		node.display();		
	}
	

	
	  
	// 得到后继节点,即删除节点的左后代
	private Node getSuccessor(Node delNode) {
		Node successor = delNode;
		Node successorParent = null;
		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;
		}
		// 任何情况下,都需要将删除节点的左子节点指向后继节点的左子节点
		successor.leftChild = delNode.leftChild;

		return successor;
	}

	// 删除
	public boolean delete(int value) {
		Node current = root; // 需要删除的节点
		Node parent = null; // 需要删除的节点的父节点
		boolean isLeftChild = true; // 需要删除的节点是否父节点的左子树

		while (true) {
			if (value == current.value) {
				break;
			} else if (value < current.value) {
				isLeftChild = true;
				parent = current;
				current = current.leftChild;
			} else {
				isLeftChild = false;
				parent = current;
				current = current.rightChild;
			}

			// 找不到需要删除的节点,直接返回
			if (current == null)
				return false;
		}

		// 分情况考虑
		// 1、需要删除的节点为叶子节点
		if (current.leftChild == null && current.rightChild == null) {
			// 如果该叶节点为根节点,将根节点置为null
			if (current == root) {
				root = null;
			} else {
				// 如果该叶节点是父节点的左子节点,将父节点的左子节点置为null
				if (isLeftChild) {
					parent.leftChild = null;
				} else { // 如果该叶节点是父节点的右子节点,将父节点的右子节点置为null
					parent.rightChild = null;
				}
			}
		}
		// 2、需要删除的节点有一个子节点,且该子节点为左子节点
		else if (current.rightChild == null) {
			// 如果该节点为根节点,将根节点的左子节点变为根节点
			if (current == root) {
				root = current.leftChild;
			} else {
				// 如果该节点是父节点的左子节点,将该节点的左子节点变为父节点的左子节点
				if (isLeftChild) {
					parent.leftChild = current.leftChild;
				} else { // 如果该节点是父节点的右子节点,将该节点的左子节点变为父节点的右子节点
					parent.rightChild = current.leftChild;
				}
			}
		}
		// 2、需要删除的节点有一个子节点,且该子节点为右子节点
		else if (current.leftChild == null) {
			// 如果该节点为根节点,将根节点的右子节点变为根节点
			if (current == root) {
				root = current.rightChild;
			} else {
				// 如果该节点是父节点的左子节点,将该节点的右子节点变为父节点的左子节点
				if (isLeftChild) {
					parent.leftChild = current.rightChild;
				} else { // 如果该节点是父节点的右子节点,将该节点的右子节点变为父节点的右子节点
					parent.rightChild = current.rightChild;
				}
			}
		}
		// 3、需要删除的节点有两个子节点,需要寻找该节点的后续节点替代删除节点
		else {
			Node successor = getSuccessor(current);
			// 如果该节点为根节点,将后继节点变为根节点,并将根节点的左子节点变为后继节点的左子节点
			if (current == root) {
				root = successor;
			} else {
				// 如果该节点是父节点的左子节点,将该节点的后继节点变为父节点的左子节点
				if (isLeftChild) {
					parent.leftChild = successor;
				} else { // 如果该节点是父节点的右子节点,将该节点的后继节点变为父节点的右子节点
					parent.rightChild = successor;
				}
			}
		}
		current = null;
		return true;
	}

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值