二叉树的通用接口
public interface ITree<E> {
public int size();//
public boolean isEmpty();
public void clear();
public void add(E element);
public void remove(E element);
public boolean contains(E element);
}
二叉树的基本实现
public abstract class BinaryTree<E> implements ITree<E>,{
public static class Node<E> {
E element;
Node<E> left;
Node<E> right;
Node<E> parent;//为了方便二叉树的基本操作,维护一个parent节点
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
/**
* 判断是否是叶子节点
* @return
*/
public boolean isLeaf() {
return left == null & right == null;
}
/**
* 判断是否是度为2的节点
* @return
*/
public boolean hasChild() {
return left != null && right != null;
}
/**
* 判断是否是左孩子
* @return
*/
public boolean isLeftChild(){
return parent!=null&&parent==parent.left;
}
/**
* 判断是否是右孩子
* @return
*/
public boolean isRightChild(){
return parent!=null&&parent==parent.right;
}
@Override
public String toString() {
return element+"_p"+parent;
}
}
public int size;
public Node<E> root;//根节点
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
root=null;
size=0;
}
/**
* 前序遍历 也可通过栈或者队列,迭代实现,后序遍历用迭代实现有些复杂。
*
* @param node
*/
public void preorderTraversal(Node<E> node) {
if (node == null) return;
System.out.println(node.element);
preorderTraversal(node.left);
preorderTraversal(node.right);
}
/**
* 中序遍历
*
* @param node
*/
public void inorderTraversal(Node<E> node) {
if (node == null) return;
inorderTraversal(node.left);
System.out.println(node.left);
inorderTraversal(node.right);
}
/**
* 后续遍历
*
* @param node
*/
public void postorderTraversal(Node<E> node) {
if (node == null) return;
postorderTraversal(node.left);
postorderTraversal(node.right);
System.out.println(node.element);
}
//层序遍历
public void leveorderTraversal() {
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);
}
}
}
//层序遍历 通过外部提供一个vistore接口的进行相应的操作
public void levelOrder(BinarySearchTree.Visitor<E> visitor) {
if (root == null || visitor == null) return;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
visitor.visit(node.element);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
/**
* 计算二叉树的高度 递归,左子树和右子树最高的加1
*
* @return
*/
public int height() {
return height(root);
}
private int height(Node node) {
if (node == null) {
return 0;
}
return 1 + Math.max(height(node.left), height(node.right));
}
/**
* 计算二叉树的高度 迭代
*
* @return
*/
public int height1() {
if (root == null)
return 0;
//树的高度
int height = 0;
//存储着每一层的元素数量
int levelSize = 1;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
levelSize--;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if (levelSize == 0) {
//意味着即将访问下一层
levelSize = queue.size();
height++;
}
}
return height;
}
//创建一个新的节点,protected是为了方便子类重写
protected Node<E> createNode(E element,Node<E> parent){
return new Node<>(element,parent);
}
/**
* 二叉树添加节点后的调整 avl
* @param node
*/
protected void afterAdd(Node<E> node){
}
/**
* 二叉树删除节点后的调整 avl
* @param node
*/
protected void afterRemove(Node<E> node){
}
/**
* 判断树是否是完全二叉树:完全二叉树最下面一层靠左边排列
* @return
*/
public boolean isCompleteTree(){
if (root==null) return false;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
boolean isLeaf=false;
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
if(isLeaf&&!node.isLeaf()){//isLeaf标志叶子节点
return false;
}
if (node.left!=null){
queue.offer(node.left);
}else if(node.right!=null){//到这里意味着左子树为空,右子树不为空一定不是完全二叉树
return false;
}
if (node.right!=null){
queue.offer(node.right);
}else{
//node.left==null&&node.right==null
//node.left!=null&&node.right==null
isLeaf=true;
}
}
return true;
}
/**
* 获取前驱节点:中序遍历的前一个节点
* 左子树的最大节点
* @param
* @return
*/
private Node<E> predecssor(Node<E> node){
if(node==null) return null;
Node<E> p=node.left;
if (p!=null){
while (p.right!=null){
p=p.right;
}
return p;
}
//从父节点中寻找
while(node.parent!=null&&node==node.parent.left){
node=node.parent;
}
//node.parent==null
//node.parent.right=node
return node.parent;
}
/**
* 中序遍历的后一个节点
* 右子树的最小节点
* @param node
* @return
*/
public Node<E> afterprocessor(Node<E> node){
if(node==null)return null;
Node<E> p=node.right;
if(p!=null){
while (p.left!=null){
p=p.left;
}
return p;
}
while (node.parent!=null&&node==node.parent.right){
node=node.parent;
}
return node.parent;
}
public static interface Visitor<E> {
void visit(E element);
}
protected void elementNotNullCheck(E element){
if(element==null){
throw new IllegalArgumentException("element is null");
}
}
二叉搜索树的实现:左子树小于根节点,右子树大于根节点,二叉搜索树的查询、新增、删除复杂度都是Ologn也就是树的高度。另外二叉搜索树的元素都应该具有可比较性。
public class BinarySearchTree<E> extends BinaryTree<E> {
private Comparator<E> comparator;//比较器,当创建bst时没有传入外部比较器,那么二叉搜素树的元素应该实现Comparable接口。
public BinarySearchTree(Comparator<E> comparator) {
this.comparator = comparator;
}
public BinarySearchTree() {
this(null);
}
@Override
public void add(E element) {
elementNotNullCheck(element);
//添加第一个节点
if (root == null) {
root = createNode(element,null);
afterAdd(root);
size++;
return;
}
//添加的不是第一个节点
//找到父节点
Node<E> parentNode = root;
Node<E> node = root;
int cmp = 0;
while (node != null) {
cmp = compare(element, node.element);
parentNode = node;
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else {
//相等
node.element = element;
return;
}
}
Node<E> newNode = createNode(element,parentNode);
if (cmp > 0) {
parentNode.right = newNode;
} else {
parentNode.left = newNode;
}
afterAdd(newNode);//该方法是用来调整平衡二叉树的
size++;
}
/**
* 优先使用比较器比较
* 返回值等于0 代表e1等于e2
* 返回值小于0 代表e1小于e2
*
* @param e1
* @param e2
* @return
*/
private int compare(E e1, E e2) {
if (comparator != null) {
return comparator.compare(e1, e2);
}
return ((Comparable<E>) e1).compareTo(e2);
}
@Override
public void remove(E element) {
remove(node(element));
}
private void remove(Node<E> node) {
if (node == null) return;
size--;
if (node.hasChild()) {//度为2的节点
//找到后继节点
Node<E> after = afterprocessor(node);
//用后继节点的值覆盖度为2的值
node.element = after.element;
//删除后继节点
node = after;
}
//删除node节点(node的度必然是1或者2)
Node<E> replacement = node.left != null ? node.left : node.right;
if (replacement != null) {//node是du为1的节点
//更改parent
replacement.parent = node.parent;
//更改parent的指向
if (node.parent == null) {
root=replacement;
} else if (node == node.parent.left) {
node.parent.left = replacement;
} else if (node == node.parent.right) {
node.parent.right = replacement;
}
//删除节点之后的处理
afterRemove(node);
} else if(node.parent==null){
//node是叶子节点并且是根节点
root=null;
afterRemove(node);
}else {
//node是叶子节点但不是根节点
if (node == node.parent.left) {
node.parent.left = null;
} else {
node.parent.right = null;
}
afterRemove(node);
}
}
//根据元素查找节点
private Node<E> node(E element){
Node<E> node=root;
while (node!=null){
int cmp=compare(element,node.element);
if (cmp==0)return node;
if(cmp>0){
node=node.right;
}else{
node=node.left;
}
}
return null;
}
@Override
public boolean contains(E element) {
return node(element)==null?false:true;
}
}
平衡二叉树:左子树和右子树的高度差的绝对值小于等于一。之所以为了平衡是防止二叉搜索树退化成一个链表,导致时间复杂度O(n).
public class AVLTree<E> extends BinarySearchTree<E> {
private static class AVLNode<E>extends Node<E>{
int height=1;//为了方便的计算二叉树的高度,此处维护一个height属性
public AVLNode(E element, Node<E> parent) {
super(element, parent);
}
@Override
public String toString() {
return element.toString();
}
/**
* 计算平衡因子:左子树的高度和右子树的高度差
* @return
*/
public int balanceFactor(){
int leftHeight=left==null?0:((AVLNode<E>)left).height;
int rightHeight=right==null?0:((AVLNode<E>)right).height;
return leftHeight-rightHeight;
}
public void updateHeight(){
int leftHeight=left==null?0:((AVLNode<E>)left).height;
int rightHeight=right==null?0:((AVLNode<E>)right).height;
height=1+Math.max(leftHeight,rightHeight);
}
//找出左右孩子种,高度高的孩子
private Node<E> tallerChild(){
int leftHeight=left==null?0:((AVLNode<E>)left).height;
int rightHeight=right==null?0:((AVLNode<E>)right).height;
if (leftHeight>rightHeight)return left;
if (leftHeight<rightHeight)return right;
return isLeftChild()?left:right;
}
}
public AVLTree() {
this(null);
}
public AVLTree(Comparator<E> comparator) {
super(comparator);
}
@Override
protected void afterAdd(Node<E> node) {
while((node=node.parent)!=null){
if (isBalance(node)){//是平衡的,无需调整,当添加完节点需要更新高度
//更新高度
updateHeight(node);
}else{
//恢复平衡
rebalance(node);
//整棵树恢复平衡
break;
}
}
}
/**
* 恢复平衡 高度最低的那个不平衡节点
* @param grand
*/
private void rebalance(Node<E> grand){
Node<E>parent=((AVLNode<E>)grand).tallerChild();
Node<E> node=((AVLNode<E>)parent).tallerChild();
if (parent.isLeftChild()){//L
if (node.isLeftChild()){//LL 右旋
roateRight(grand);
}else{//LR
roateLeft(parent);
roateRight(grand);
}
}else{//R
if (node.isLeftChild()){//RL
roateRight(parent);
roateLeft(grand);
}else{//RR
roateLeft(grand); //左旋
}
}
}
//统一旋转的方法 无需区分左旋和右旋等情况
private void reblance2(Node<E> grand){
Node<E>parent=((AVLNode<E>)grand).tallerChild();
Node<E> node=((AVLNode<E>)parent).tallerChild();
if (parent.isLeftChild()){//L
if(node.isLeftChild()){
roate(grand,node.left,node,node.right,parent,parent.right,grand,grand.right);
}else{
roate(grand,parent.left,parent,node.left,node,node.right,grand,grand.right);
}
}else{//R
if (node.isLeftChild()) {//R
roate(grand,grand.left,grand,node.left,node,node.right,parent,parent.right);
}else{
roate(grand,grand.left,grand,parent.left,parent,node.left,node,node.right);
}
}
}
private void roate(Node<E> r,
Node<E> a,Node<E> b,Node<E> c,
Node<E> d,
Node<E> e, Node<E> f, Node<E> g){
//让d成为这颗子树的根节点
d.parent=r.parent;
if(r.isLeftChild()){
r.parent.left=d;
}else if(r.isRightChild()){
r.parent.right=d;
}else{
root=d;
}
//a-b-c
b.left=a;
if(a!=null) a.parent=b;
b.right=c;
if(c!=null) c.parent=b;
updateHeight(b);
//e-f-g
f.left=e;
if(e!=null){
e.parent=f;
}
f.right=g;
if(g!=null){
g.parent=f;
}
updateHeight(f);
//b-d-f
d.left=b;
d.right=f;
b.parent=d;
f.parent=d;
updateHeight(d);
}
//左旋转
private void roateLeft(Node<E> grand){
Node<E> parent=grand.right;
Node<E> child=parent.left;
grand.right=child;
parent.left=grand;
afterRote(grand,parent,child);
}
//右旋转
private void roateRight(Node<E> grand){
Node<E> parent=grand.left;
Node<E> child=parent.right;
grand.left=child;
parent.right=grand;
afterRote(grand,parent,child);
}
private void afterRote(Node<E> grand,Node<E> parent,Node<E> child){
parent.parent= grand.parent;
if (grand.isLeftChild()){
grand.parent.left=parent;
}else if(grand.isRightChild()){
grand.parent.right=parent;
}else{
root=parent;
}
//更新child的parent
if(child!=null){
child.parent=grand;
}
//更新grand的parent
grand.parent=parent;
//更新高度
updateHeight(grand);
updateHeight(parent);
}
private boolean isBalance(Node<E> node){
return Math.abs(((AVLNode<E>)node).balanceFactor())<=1;
}
private void updateHeight(Node<E> node){
((AVLNode<E>)node).updateHeight();
}
@Override
protected Node<E> createNode(E element, Node<E> parent) {
return new AVLNode<>(element,parent);
}
@Override
protected void afterRemove(Node<E> node) {//删除完节点后,需要调整平衡,最坏的情况是父节点以上的节点全部
//失去平衡 都进行平衡。
while((node=node.parent)!=null){
if (isBalance(node)){
//更新高度
updateHeight(node);
}else{
//恢复平衡
rebalance(node);
//整棵树恢复平衡
}
}
}
}