Person类:
package dataStruct.tree.binarySearchTree;
public class Person {
private int age;
public Person(int age){
this.age = age;
}
// @Override
// public int compareTo(Person p) {
// return age - p.age;
// }
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return "age:"+age;
}
}
BinarySearchTree类
package dataStruct.tree.binarySearchTree;
import dataStruct.tree.printer.BinaryTreeInfo;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
/**
* 二叉搜索树:
* Tree定义了要实现哪些方法。
* @param <E>
*/
public class BinarySearchTree<E > implements BinaryTreeInfo {
//根节点
public Node<E> root ;
//节点数目
public int size = 0;
//提供比较器
public Comparator<E> comparator;
public BinarySearchTree(){
this(null);
}
public BinarySearchTree(Comparator<E> comparator){
this.comparator = comparator;
}
public int size() {
return size;
}
public boolean isEmpty() {
return false;
}
public void clear() {
}
/**
* 添加节点
* @param element
*/
public void add(E element) {
elementNotNullCheck(element); //校验element是否不为null
//添加第一个节点
if (root == null){
root = new Node(element,null);
size++;
return;
}
//添加的不是第一个节点
//1.先找到父节点parent,以及记录插入节点的方向
Node<E> node = root;
Node<E> parent = root;//记录父节点
int res = 0;//记录方向
while(node != null){
parent = node;
res = compare(element , node.element);
//res>0 说明在节点的右边
if (res > 0){
node = node.right;
}
//res <0 说明在节点的左边
else if(res < 0){
node = node.left;
}else{//相等
node.element = element;
return;
}
}
//2.通过节点方向,插入新节点
Node<E> newnode = new Node<>(element,parent);
if ( res > 0 ){
parent.right = newnode;
}else{
parent.left = newnode;
}
size++;
}
/**
* 返回的值>0:e1>e2
* 返回的值<0:e1<e2
* 返回的值=0:e1=e2
* @param e1
* @param e2
* @return
*/
public int compare(E e1, E e2){
//二叉搜索树一定是可以根据对象来进行比较的
//如果对象有自己的比较器,则只需传入两个参数即可
if (comparator != null){
return comparator.compare(e1,e2);
}
//如果没有自己的比较器
return ((Comparable<E>)e1).compareTo(e2);
}
/**
* 根据元素删除节点
* @param element
*/
public void remove(E element) {
remove(node(element));
}
public void remove(Node<E> node){
if ( node == null ) return;
//如果node不等于空
size--;
//1.先考虑度为2的节点,
// 因为是用后继节点的值替换跟节点,
// 并把后继节点删除(而度为2的后继节点的度必为1或0,所以防止逻辑重叠)
if(node.hasTwoChildren()){
Node<E> p = successor(node);//找后继节点
//用后继节点的值覆盖该节点
node.element = p.element;
//删除后继节点,让后继节点替换node节点,后面会考虑删除度为1的节点
node = p ;
}
//删除节点node
// 2.到这一步,此时节点的度必为1或0;
Node<E> child = node.left != null ? node.left : node.right;
if (child != null ){// node是度为1的节点
//更改parent
child.parent = node.parent;
//更改parent的left、right的指向
if( node.parent == null ){//node是根节点,并且度为1
root = child;
}
else if( child == node.parent.left ){//child节点是左节点
node.parent.left = child;
}else{
node.parent.right = child;
}
}else if( node.parent == null ){//node是叶子节点,并且是根节点
root = null;
}else{//节点为叶子节点
if(node == node.parent.left){
node.parent.left = null;
}else{// node == node.parent.right
node.parent.right = null;
}
}
}
public boolean contains(E element) {
return node(element) != null;
}
/**
* 校验element是否为空
* @param element
*/
public void elementNotNullCheck(E element){
if (element == null){
//非法参数异常
throw new IllegalArgumentException("element must not is null");
}
}
@Override
public Object root() {
return root;
}
@Override
public Object left(Object node) {
return ((Node<E>)node).left;
}
@Override
public Object right(Object node) {
return ((Node<E>)node).right;
}
@Override
public Object string(Object node) {
return ((Node<E>)node).element;
}
/**
* 内部类:
* 声明树的结构
* @param <E>
*/
public static class Node<E>{
E element;
Node<E> left;
Node<E> right;
Node<E> parent;
/**
* 构造函数没有左、右孩子节点
* 因为节点可能是叶子节点
* @param element
* @param parent
*/
public Node(E element, Node<E> parent){
this.element = element;
this.parent = parent;
}
/**
* 判断节点的度是否为2;
* @return
*/
public boolean hasTwoChildren(){
return left == null && right == null;
}
/**
* 判断是否为叶子节点
* @return
*/
public boolean isLeaf(){
return left == null && right == null;
}
/**
* 判断是否存在左右孩子节点
* @return
*/
public boolean isHasTwoNode(){
return left != null && right != null;
}
}
/**
* 判断是否为完全二叉树
* @return
*/
public boolean isComplete(){
if ( root == null ) return false;
Queue<Node<E>> queue =new LinkedList<>();
queue.offer(root);
boolean leaf = false;
while(!queue.isEmpty()){
Node<E> node = queue.poll();
if (leaf && !node.isLeaf()){
return false;
}
if (node.isHasTwoNode()){
queue.offer(node.left);
queue.offer(node.right);
}
else if (node.left == null && node.right != null){
return false;
}else{
leaf = true;
if (node.left != null){
queue.offer(node.left);
}
}
}
return true;
}
public boolean completeBinaryTree(){
if ( root == null ) return false;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
boolean flag = false;
while(!queue.isEmpty()){
Node<E> node = queue.poll();
if (flag && !node.isLeaf()){
return false;
}
if (node.left != null){
queue.offer(node.left);
}else if(node.right != null){
return false;//这说明node.left == null && node.right != null
}
if (node.right != null){
queue.offer(node.right);
}else{
//2种情况
// node.left != null && node.right == null
// node.left == null && node.right == null
//总结:后面遍历的节点必须是叶子节点
flag = true;
}
}
return true;
}
/**
* 前序遍历
*/
public void preorderTraversal() {
preorderTraversal(root);
}
public void preorderTraversal(Node<E> node){
if (node == null ) return;
System.out.println(node.element);
preorderTraversal(node.left);
preorderTraversal(node.right);
}
//后序遍历
public void postOrderTraversal(){
postOrderTraversal(root);
}
public void postOrderTraversal(Node<E> node){
if (node == null ) return;
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.println(node.element);
}
/**
* 中跟遍历
*/
public void middleOrderTraversal(){middleOrderTraversal(root);}
public void middleOrderTraversal(Node<E> node){
if (node == null ) return;
middleOrderTraversal(node.left);
System.out.println(node.element);
middleOrderTraversal(node.right);
}
//层次遍历
public void levelOrderTraversal(){
if (root == null) return;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);//根节点入队
while(!queue.isEmpty()){
Node<E> node = queue.poll();
System.out.println(node.element);//输出节点元素
if ( node.left != null ){
queue.offer(node.left);
}
if ( node.right != null ){
queue.offer(node.right);
}
}
}
public String toString(){
StringBuilder sb = new StringBuilder();
toString(root,sb,"");
return sb.toString();
}
public void toString(Node<E> node,StringBuilder sb,String prefix){
if (node == null) return;
sb.append(prefix).append("---").append(node.element).append("\n");
toString(node.left,sb,prefix+"---L");
toString(node.right,sb,prefix+"---R");
}
/**
* 递归求解:
* 求二叉树的高度
*/
public int height(){
return height(root);
}
public int height(Node<E> node){
if (node == null) return 0;
return 1 + Math.max(height(node.left),height(node.right));
}
/**
* 非递归求树的高度
* 层序遍历
*/
public int getTreeHeight(){
if (root == null ) return 0;
Queue<Node<E>> queue = new LinkedList();
queue.offer(root);
int levelNum = 1; //存取 层的节点数
int height = 0;
while(!queue.isEmpty()){
Node<E> node = queue.poll();//出队
levelNum--;
if (node.left != null){
queue.offer(node.left);
}
if (node.right != null){
queue.offer(node.right);
}
if (levelNum == 0){
levelNum = queue.size();
height++;
}
}
return height;
}
/**
* 根据元素查找node
* @param element
* @return
*/
public Node<E> node(E element){
Node<E> node = root;
while( node != null ){
int res = compare(element, node.element);
if (res == 0) return node;
else if( res > 0 ){
node = node.right;
}else{
node = node.left;
}
}
return null;
}
/**
* 寻找当前节点的前驱节点
* @param node
* @return
*/
public Node<E> predecessor(Node<E> node){
if ( node == null ) return null;
Node<E> p =node.left;
if ( p != null ){
//1.当前节点的左子树不为空
while(p.right != null){
p = p.right;
}
return p;
}
//2.当前节点的左子树为空
// 从父节点、祖父节点中寻找前驱节点
while(node.parent != null && node == node.parent.left){
node = node.parent;
}
//3.循环到这有两种情况
//3.1 node.parent == null;-->即前驱节点为null(也可以是node.parent)
//3.2 node = node.parent.right;-->即前驱节点为node.parent
return node.parent;
}
/**
* 寻找后驱节点
* @param node
* @return
*/
public Node<E> successor(Node<E> node){
if (node == null ) return null;
Node<E> p = node.right;
if (p != null ){
// 1.前驱节点在左子树当中(right.left.left.left....)
while( p.left != null){
p = p.left;
}
return p;
}
//2.从父节点,祖父节点寻找前驱节点
while(node.parent != null && node == node.parent.right){
node = node.parent;
}
return node.parent;
}
}
测试类
package dataStruct.tree.binarySearchTree;
import dataStruct.tree.printer.BinaryTrees;
import java.util.Comparator;
import java.util.Scanner;
public class BinarySearchTreeTest<E> {
public static class Mycompare implements Comparator<Person>{
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}
public static void test1(){
int [] arr = new int[]{7,4,9,2,5,8,11,3};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0 ; i < arr.length ; i++){
bst.add(arr[i]);
}
BinaryTrees.println(bst);
}
public static void test2(){
//1.匿名内部类实现Comparator接口
BinarySearchTree<Person> bst2 = new BinarySearchTree(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
});
bst2.add(new Person(7));
bst2.add(new Person(4));
bst2.add(new Person(2));
bst2.add(new Person(1));
bst2.add(new Person(3));
bst2.add(new Person(5));
bst2.add(new Person(9));
bst2.add(new Person(8));
bst2.add(new Person(11));
bst2.add(new Person(12));
BinaryTrees.println(bst2);
// bst2.preorderTraversal();//先根遍历
// bst2.middleOrderTraversal();//中须遍历
// bst2.postOrderTraversal();//后序遍历
// bst2.levelOrderTraversal();
}
public static void test3(){
BinarySearchTree<Integer> bst3 = new BinarySearchTree();
bst3.add(7);
bst3.add(4);
bst3.add(2);
bst3.add(1);
bst3.add(3);
bst3.add(5);
bst3.add(9);
bst3.add(8);
bst3.add(11);
// bst3.add(12);
// System.out.println(bst3);
BinaryTrees.println(bst3);
// System.out.println(bst3.height());
boolean flag = bst3.completeBinaryTree();
System.out.println("是否为完全二叉树:"+flag);
System.out.println("请输入要删除的节点:");
Scanner sc = new Scanner(System.in);
int delNum = sc.nextInt();
bst3.remove(delNum);
BinaryTrees.println(bst3);
}
public static void test4(){
BinarySearchTree<Integer> bst4 = new BinarySearchTree();
bst4.add(7);
bst4.add(4);
bst4.add(2);
bst4.add(1);
bst4.add(3);
bst4.add(5);
bst4.add(9);
bst4.add(8);
bst4.add(11);
BinaryTrees.println(bst4);
System.out.println("请输入要查找前驱节点的节点值:");
Scanner sc = new Scanner(System.in);
int findNum = sc.nextInt();
System.out.println(bst4.predecessor(bst4.node(findNum)).element);
System.out.println("请输入要删除的节点");
int delNum = sc.nextInt();
bst4.remove(delNum);
BinaryTrees.println(bst4);
}
public static void main(String[] args) {
test4();
}
}