二分搜索树
今天七夕,然后我再公司宿舍写代码!!!好吧~我承认我酸了,不想进行讲解,我就是将今天的事记录下,而且也不知道咋回事,回来倒头就睡,可能是算法太耗费脑子了吧,也不知道是因为算法还是情人节闹的~反正就是特么蔫吧了一整天,现在的时间是2019年8月7日23:09:19,代码你们粘过去也运行不了,因为里面用到了我自己写的队列Queue
package com.myTree;
import com.xsh.April_Month23Day_Queue.CommonQueue;
import com.xsh.April_Month23Day_Queue.Queue;
/**
*
* @author lenovo
*
* 二分搜索树
*
*/
public class BST<E extends Comparable> {
// Node 节点
private class Node<E extends Comparable>{
// 节点的值
private E value;
// 左子节点
private Node left;
// 右子节点
private Node right;
public Node(E value) {
this.value = value;
this.left = null;
this.right = null;
}
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
}
// 根节点
private Node root;
// 节点的个数
private int size;
// 默认构造函数
public BST() {
this.root = null;
this.size = 0;
}
// 添加构造节点 ---> 对外暴露方法
public void add(E value) {
// 进一步深化 迭代算法
if (root == null) {
root = new Node(value);
return;
}
add(root,value);
}
// 内部实际实现算法
private void add(Node node,E value) {
// 递归终止条件
if (value.compareTo(node.value) < 0 && node.left == null) {
size++;
node.left = new Node(value);
} else if(value.compareTo(node.value) > 0 && node.right == null) {
size++;
node.right = new Node(value);
}
// 递归条件
if (value.compareTo(node.value) < 0) {
add(node.left,value);
} else if(value.compareTo(node.value) > 0) {
add(node.right,value);
}
}
// 判断特定节点的值是否存在 --- 对外暴露方法
public boolean isExist(E value) {
if (root == null) return false;
return isExist(root,value);
}
// 内部真正实现的方法
private boolean isExist(Node node,E value) {
if (value.compareTo(node.value) == 0) {
return true;
} else if (value.compareTo(node.value) < 0 && node.left == null) {
return false;
} else if(value.compareTo(node.value) > 0 && node.right == null) {
return false;
}
if (value.compareTo(node.value) < 0) {
return isExist(node.left,value);
} else{ //(value.compareTo(node.value) > 0)
return isExist(node.right,value);
}
}
// 前序遍历 --- 又称根序遍历 --- 根左右
public void preOrder() {
if (root == null) throw new IllegalArgumentException("二分搜索树为NULL");
preOrder(root);
}
// 内部真正实现 -- 前序遍历
private void preOrder(Node root) {
if (root == null)
return;
System.out.println(root.value);
preOrder(root.left);
preOrder(root.right);
}
// 后序遍历 --- 又称后根遍历 --- 左右根 --- 对外暴露实现的方法
public void afterOrder() {
if (root == null) throw new IllegalArgumentException("当前二分搜索树为NULL");
afterOrder(root);
}
// 内部真正实现 -- 后序遍历
private void afterOrder(Node node) {
if (node == null) return;
afterOrder(node.left);
afterOrder(node.right);
System.out.println(node.value);
}
// 中序遍历 --- 又叫做中根遍历 --- 左根右 --- 对外暴露实现的方法
public void midOrder() {
if (root == null) throw new IllegalArgumentException("二叉树为NULL");
midOrder(root);
}
// 内部真正实现 -- 中序遍历
private void midOrder(Node node) {
if (node == null) return;
midOrder(node.left);
System.out.println(node.value);
midOrder(node.right);
}
// 查找该二叉树的最小值 -- 对外暴露的方法
public E min() {
if (root == null) throw new IllegalArgumentException("当前二叉树为NULL");
Node node = min(root);
return (E) node.value;
}
// 内部真正实现 -- 查找二叉树的最小值
private Node min(Node node) {
if (node.left == null)
return node;
return min(node.left);
}
// 查找二叉树的最大值 -- 对外暴露的方法
public E max() {
if (root == null) throw new IllegalArgumentException("当前二叉树为NULL");
Node node = max(root);
return (E) node.value;
}
// 内部真正实现 -- 查找二叉树的最大值
private Node max(Node node) {
if(node.right == null) return node;
return max(node.right);
}
// 层序遍历 -- 一层一层来,这个跟前面的操作有很大的区别,这个是广度优先算法
// bsf --- Breadth First Search 广度优先算法
public void bfsOrder() {
if(root == null) throw new IllegalArgumentException("当前二叉树为NULL");
bfsOrder(root);
}
// 层序遍历 -- 一层一层来,这个跟前面的操作有很大的区别,这个是广度优先算法
// bsf --- Breadth First Search 广度优先算法
private void bfsOrder(Node node) {
// 创建一个队列
Queue queue = new CommonQueue();
queue.enqueue(root);
while (queue != null) {
Node curNode = (Node) queue.dequeue();
System.out.print(curNode.value + " ");
if (curNode.left != null)
queue.enqueue(curNode.left);
if (curNode.right != null)
queue.enqueue(curNode.right);
}
}
// 从二分苏所述中删除最小值所在的节点,返回最小值
public E removeMin() {
E ret = min();
// BEGIN
root = removeMin(root);
// END
return ret;
}
// 删除以node为根的二分搜索树中的最小节点
// 返回删除节点后新的二分搜索树的根
private Node removeMin(Node node) {
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
size--;
return rightNode;
}
// 留存疑问
node.left = removeMin(node.left);
return node;
}
// 从二分搜索树中删除最大值所在节点
public E removeMax(){
E ret = max();
// BEGIN
// END
return ret;
}
// 删除掉以node为根的二分搜索树中的最大节点
// 返回删除节点后新的二分搜索树的根
private Node removeMax(Node node){
if (node.right == null) {
Node leftNode = node.left;
node.left = null;
size--;
return leftNode;
}
node.right = removeMax(node.right);
return node;
}
// 判断当前二分搜索树是否存在其他元素
public boolean isEmpty() {
return size == 0;
}
// 从二分搜索树中删除元素为e的
public void remove(E e) {
root = remove(root,e);
}
// 删除以node为根的二分搜索树中值为e的节点,递归算法
// 返回删除节点后新的二分搜索树的根
public Node remove(Node node,E e) {
// 当前二分搜索树为NULL,所以要删除的元素不存在 --- 返回null
if (node == null) return null;
// 这里面需要再纸上看一下过程
if (e.compareTo(node.value) < 0) {
node.left = remove(node.left,e);
return node;
} else if(e.compareTo(node.value) > 0) {
node.right = remove(node.right,e);
return node;
} else { // e == node.e
// 待删除节点左子树为空的情况
if (node.left == null) {
Node rightNode = node.right;
node.right = null;
size --;
return rightNode;
}
// 待删除节点右子树为空的情况
if (node.right == null) {
Node leftNode = node.left;
node.left = null;
size --;
return leftNode;
}
// 待删除节点左右子树均不为空的情况
// 找到比待删除节点大的最小节点,即待删除节点右子树的组消极诶单
// 用这个节点顶替待删除节点的位置
/* 后继节点,有大用 */
Node successor = min(node.right);
successor.right = removeMin(node.right);
size++;
successor.left = node.left;
node.left = node.right = null;
size--;
return successor;
}
}
}
睡了睡了,明年的这个节日可不能这个样子了。