package oder;
/*二叉树*/
import java.util.ArrayList;
@SuppressWarnings("all")
public class BinaryTree {
private Node root;//根节点
public BinaryTree() {
root = null;
}
//关键字查找节点
public Node find(int key){
Node cur = root;//从根节点开始查找
if(cur == null){
return null;
}
while(cur.age != key){
if(cur.age < key){
cur = cur.leftChild;//如果关键字比当前节点小,转向左子节点
}else{
cur = cur.rightChid;//如果关键字不小于当前节点,转向右子节点
}
if(cur == null){
return null;
}
}
return cur;
}
//插入新节点
public void insert(Node node){
if(node == null){
root = node;//如果树为空,则新插入的节点为根节点
}else{
Node cur = root;
while(true){
if(node.age < cur.age){
if(cur.leftChild == null){
cur.leftChild = node;//找到要插入节点的父节点
return;
}
cur = cur.leftChild;
}else{
if(cur.rightChid == null){
cur.rightChid = node;
return;
}
cur = cur.rightChid;
}
}
}
}
//删除指定节点
public boolean delete(Node node){
if(root == null){
return false;//如果为空树,则直接返回false
}
boolean isLeftChild = true;//是否为父节点的左子节点
Node cur = root;//需要删除的节点
Node parent = null;//需要删除的父节点
while(cur.age != node.age){//确定要删除的节点和其父节点
parent = cur;
if(node.age < cur.age){
cur = cur.leftChild;
}else{
isLeftChild = false;
cur = cur.rightChid;
}
if(cur == null){
return false;//没有找到要删除的
}
}
if(cur.leftChild == null && cur.rightChid == null){//目标节点为叶子节点
if(cur == null){//要删除的为根节点
root = null;
}else if(isLeftChild){
//要删除的不是根节点,则该节点肯定有父节点,该节点删除后,需要将父节点指向它的引用置空
parent.leftChild = null;
}else{
parent.rightChid = null;
}
}else if(cur.leftChild == null){
if(cur == null){
root = cur.rightChid;
}else if(isLeftChild){
parent.leftChild = cur.rightChid;
}else{
parent.rightChid = cur.rightChid;
}
}else if(cur.rightChid == null){
if(cur == null){
root = cur.leftChild;
}else if(isLeftChild){
parent.leftChild = cur.leftChild;
}else{
parent.rightChid = cur.rightChid;
}
}else{//有两个子节点,第一步要找到欲删除节点的后继节点
Node successor = cur.rightChid;
Node successorParent = null;
while(successor.leftChild != null){
successorParent = successor;
successor = successor.leftChild;
}
//欲删除的右子节点是它的后继,证明该后继无左子节点,则将以该后继节点为根的子树上移即可
if(successorParent == null){
if(cur == root){//要删除的为根节点,将后继设置为根,且根的左子节点设置为欲删除的节点的左子节点
root = successor;
root.leftChild = cur.leftChild;
}else if(isLeftChild){
parent.leftChild = successor;
successor.leftChild = cur.leftChild;
}else{
parent.rightChid = successor;
successor.leftChild = cur.leftChild;
}
}else{//欲删除的节点的后继不是它的右子节点
successorParent.leftChild = successor.rightChid;
successor.rightChid = cur.rightChid;
if(cur == root){
root = successor;
successor.leftChild = cur.leftChild;
}else if(isLeftChild){
parent.leftChild = root;
successor.leftChild = cur.leftChild;
}else{
parent.leftChild = successor;
successor.leftChild = cur.leftChild;
}
}
}
return true;
}
public static final int PREORDER = 1;//前序遍历
public static final int INORDER = 2;//中序遍历
public static final int POSTORDER =3;//后序遍历
//遍历
public void traverse(int type){
switch(type){
case 1:
System.out.println("前序遍历:\t");
preorder(root);
System.err.println();
break;
case 2:
System.out.println("中序遍历:\t");
inorder(root);
System.out.println();
break;
case 3:
System.out.println("后续遍历:\t");
postorder(root);
System.out.println();
break;
}
}
//前序遍历
private void preorder(Node currentRoot) {
if(currentRoot != null){
System.out.println(currentRoot.age + "\t");
preorder(currentRoot.leftChild);
preorder(currentRoot.rightChid);
}
}
//中序遍历
private void inorder(Node currentRoot) {
if(currentRoot != null){
inorder(currentRoot.leftChild);//先对当前节点的左子树进行中序遍历
System.out.println(currentRoot.age + "\t");//然后访问当前节点
inorder(currentRoot.rightChid);//最后对当前节点的右子树进行中序遍历
}
}
//后续遍历
private void postorder(Node currentRoot) {
if(currentRoot != null){
System.out.println(currentRoot.age + "\t");
postorder(currentRoot.leftChild);
postorder(currentRoot.rightChid);
}
}
//私有方法,用迭代方法来获得左子树和右子树的最大深度,返回两者的最大值
private int getDepth(Node currentRoot,int initDeep){
int deep = initDeep;//当前节点已达到的深度
int leftDeep = initDeep;
int rightDeep = initDeep;
if(currentRoot.leftChild != null){
getDepth(currentRoot.leftChild, deep+1);
}else if(currentRoot.rightChid != null){
getDepth(currentRoot.rightChid, deep+1);
}
return Math.max(leftDeep, rightDeep);
}
//获取树的深度
public int getTreeDepth(){
if(root == null){
return 0;
}
return getDepth(root, 1);
}
//返回关键值得最大节点
public Node getMax(){
if(isEmpty()){
return null;
}
Node cur = root;
if(cur.rightChid != null){
cur = cur.rightChid;
}
return cur;
}
//返回关键值最小节点
public Node getMin(){
if(isEmpty()){
return null;
}
Node cur = root;
if(cur.rightChid != null){
cur = cur.rightChid;
}
return cur;
}
//以树得形式打印出该树
public void displayTree(){
int treeDepth = getTreeDepth();
ArrayList<Node> currentLayerNodes = new ArrayList<Node>();
currentLayerNodes.add(root);//存储该层所有节点
int layerIndex = 1;
while(layerIndex <= treeDepth){
int nodeBlankNum = (int)(Math.pow(2, treeDepth-layerIndex)-1);//在节点之前和之后应该打印几个空位
for(int i = 0; i < currentLayerNodes.size(); i++){
Node node = currentLayerNodes.get(i);
printBlank(nodeBlankNum);//节点之前打印空位
if(node == null){
System.out.println("*\t");
}else{
System.out.println("* "+node.age+"\t");
}
printBlank(nodeBlankNum);//节点之后打印空位
System.out.println("*\t");//补齐空位
}
System.out.println();
layerIndex++;
currentLayerNodes = getAllNodeOfThisLayer(currentLayerNodes);//获取下一层所有得节点
}
}
private ArrayList<Node> getAllNodeOfThisLayer(ArrayList<Node> currentLayerNodes) {
ArrayList<Node> nodeList = new ArrayList<Node>();
Node parentNode;
for(int i = 0; i < currentLayerNodes.size(); i++){
parentNode = currentLayerNodes.get(i);
if(parentNode != null){
//如果上层左子节点存在,加入集合,如果不存在,用null代替,一样加入集合
if(parentNode.leftChild != null){
nodeList.add(parentNode.leftChild);
}else{
nodeList.add(null);
}
if(parentNode.rightChid != null){
nodeList.add(parentNode.rightChid);
}else{
nodeList.add(null);
}
}else{
//如果上层父节点不存在,用两个null占位,代表左右两个子节点
nodeList.add(null);
nodeList.add(null);
}
}
return null;
}
public class Node{
int age;
String name;
Node leftChild;//左子节点的引用
Node rightChid;//右子节点的引用
public Node(int age,String name) {
this.age = age;
this.name = name;
}
//打印该节点的信息
public void displayNode(){
System.out.println("name:" + name + ",age:" + age);
}
}
//打印指定个数得空位
public void printBlank(int num){
for(int i= 0; i < num; i++){
System.out.println("*\t");
}
}
//判空
public boolean isEmpty(){
return (root == null);
}
//判断是否为叶子节点
public boolean isLeaf(Node node){
return (node.leftChild != null || node.rightChid != null);
}
//获取根节点
public Node getRoot(){
return root;
}
}