class TreeNode{
int data;
TreeNode left,right;
public TreeNode(int data){
this.data=data;
left=null;
right=null;
}
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* 实现二叉排序树
* 二叉排序树:它或者是一棵空树,或者是具有如下性质的一棵树:
* ①如果左子树不为空,那么左子树上所有节点的值均小于等于它的根节点的值;
* ②如果右子树不为空,那么右子树上所有节点的值均大于等于它的根节点的值;
* ③左右子树分别也是二叉排序树。
*/
public class MyBinaryTree {
private TreeNode root;
public MyBinaryTree(){
root=null;
}
//将数值输入构建二叉树
public void buildTree(int [] data){
for(int i=0;i<data.length;i++){
insert(data[i]);
}
}
//插入
public void insert(int data){
TreeNode newNode=new TreeNode(data);
if(root==null){
root=newNode;
}else{
TreeNode current=root;
TreeNode parent;
while(true){//寻找插入的位置
parent=current;
if(data<current.data){
current=current.left;
if(current==null){
parent.left=newNode;
return ;
}
}else{
current=current.right;
if(current==null){
parent.right=newNode;
return ;
}
}
}
}
}
//删除
public void delete(int data){
if(root==null){
return ;
}
if(root.data==data){//删除根节点
TreeNode newRoot=newRoot(root);
newRoot.left=root.left;
newRoot.right=root.right;
root=newRoot;
return ;
}else {//删除非根节点
TreeNode parent=root;
TreeNode current=root;
while(true){
if(current.data>data){
parent=current;
current=current.left;
if(current==null){
return ;
}
}else if(current.data<data){
parent=current;
current=current.right;
if(current==null){
return ;
}
}else{
TreeNode left=current.left;
TreeNode right=current.right;
int flag=0;
if(parent.left==current){
flag=1;
}
TreeNode node=newRoot(current);
if(node!=left){//这句必须得加
node.left=left;
}
node.right=right;
if(flag==1){
parent.left=node;
}else{
parent.right=node;
}
return ;
}
}
}
}
public TreeNode newRoot(TreeNode root){
if(root.left==null){
TreeNode node=root.right;
root.right=null;
return node;
}else if(root.right==null){
TreeNode node=root.left;
root.left=null;
return node;
}else{
TreeNode parent=root;
TreeNode node=root.left;
while(node.right!=null){
parent=node;
node=node.right;
}
if(node==parent.left){//这句必须得加
return node;
}else{
parent.right=null;
}
return node;
}
}
//前序遍历
public void preOrder(TreeNode localRoot){
if(localRoot!=null){
System.out.println(localRoot.data);
preOrder(localRoot.left);
preOrder(localRoot.right);
}
}
public void preOrder(){
this.preOrder(root);
}
//中序遍历
public void inOrder(TreeNode localRoot){
if(localRoot!=null){
inOrder(localRoot.left);
System.out.println(localRoot.data);
inOrder(localRoot.right);
}
}
public void inOrder(){
this.inOrder(root);
}
//后序遍历
public void postOrder(TreeNode localRoot){
if(localRoot!=null){
postOrder(localRoot.left);
postOrder(localRoot.right);
System.out.println(localRoot.data);
}
}
public void postOrder(){
this.postOrder(root);
}
//深度优先遍历
public void dfs(TreeNode localRoot){
if(localRoot==null){
return ;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node=stack.pop();
System.out.println(node.data);
if(node.right!=null){
stack.push(node.right);
}
if(node.left!=null){
stack.push(node.left);
}
}
}
public void dfs(){
this.dfs(root);
}
//广度优先遍历
public void bfs(TreeNode localRoot){
if(localRoot==null){
return ;
}
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(localRoot);
while(!queue.isEmpty()){
TreeNode node=queue.poll();
System.out.println(node.data);
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
}
public void bfs(){
this.bfs(root);
}
/**
* 已知前序遍历和中序遍历,如何求后序遍历
* 步骤:
* 1.确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素,即先序遍历的第一个节点就是二叉树的根节点;
* 2.求解树的子树。找到根在中序遍历的位置,位置在左边是根的左子树,位置在右边是根的右子树,如果根节点左边或右边为空,那么该方向子树为空;
* 如果根节点左边和右边都为空,那么根节点已经为叶子节点;
* 3.对二叉树的左右子树分别进行步骤1,2,直到求出二叉树结构为止。
*/
public void initTree(int [] preOrder,int [] inOrder){//由前序遍历和中序遍历结果重新构造二叉排序树
this.root=this.initTree(preOrder,0,preOrder.length-1,inOrder,0,inOrder.length-1);
//构造出二叉树之后后序遍历二叉树
this.postOrder();
}
public TreeNode initTree(int [] preOrder,int start1,int end1,int [] inOrder,int start2,int end2){
if(start1>end1 || start2>end2){
return null;
}
int rootData=preOrder[start1];
TreeNode head=new TreeNode(rootData);
//找到根节点在中序遍历中的位置
int rootIndex=findIndexInArray(inOrder,rootData,start2,end2);
head.left=initTree(preOrder,start1+1,start1+rootIndex-start2,inOrder,start2,rootIndex-1);
head.right=initTree(preOrder,start1+rootIndex-start2+1,end1,inOrder,rootIndex+1,end2);
return head;
}
public int findIndexInArray(int [] inOrder,int data,int start,int end){
for(int i=start;i<=end;i++){
if(inOrder[i]==data){
return i;
}
}
return -1;
}
/**
* 求二叉树中节点的最大距离
* 问题描述:节点的距离是指这两个节点之间边的个数。写一个程序求一棵二叉树中相聚最远的两个节点之间的距离。
* 思路:距离最远的两个节点在二叉树的分布情况有三种:
* ①相距最远的两个节点都在根节点的左子树上,则在根节点的左子树上进行求解;
* ②相距最远的两个节点都在根节点的右子树上,则在根节点的右子树上进行求解;
* ③相距最远的两个节点一个在根节点的左子树上,另一个在根节点的右子树上,则分别求出这两个点到根节点的距离再相加;
*/
public int maxDistance(TreeNode localRoot){
if(localRoot==null){
return 0;
}
if(localRoot.left==null || localRoot.right==null){
return 1;
}
int result=0;
int leftMaxDistance=dfs_distance(localRoot.left);
int rightMaxDistance=dfs_distance(localRoot.right);
result=Math.max(maxDistance(localRoot.left), maxDistance(localRoot.right));
result=Math.max(result, leftMaxDistance+rightMaxDistance);
return result;
}
public int dfs_distance(TreeNode node){
if(node==null){
return 0;
}
if(node.left==null && node.right==null){
return 1;
}
return Math.max(dfs_distance(node.left), dfs_distance(node.right))+1;
}
public static void main(String [] args){
MyBinaryTree mbt=new MyBinaryTree();
int [] array={20,10,21,5,15,3,8,12,17,2,4,7,9,11,16,18};
mbt.buildTree(array);
System.out.println(mbt.maxDistance(mbt.root));
mbt.delete(5);
mbt.bfs();
}
}
本博客内容来自《Java程序员面试笔试宝典》