文章目录
前言
二分搜索树:在二叉树的基础上,任意一个节点满足大于左子树中的所有节点,小于右子树中的所有节点。
一、二叉树
1、为什么要有树结构:
树结构本身是一种天然的组织结构--高效
2、二叉树非常重要的特性:
3、满二叉树:
- 二叉树每个结点最多有两个孩子;
- 二叉树每个结点最多有一个父亲;
- 二叉树具有天然递归结构;
- 每个结点的左子树也是二叉树;
- 每个结点的右子树也是二叉树;
4、二叉树不一定是“满”的
5、二分搜索树
注意:存储的元素必须具有可比性
二、二分搜索树的性质
1、定义二分搜索树
public class BinarySearchTree<T extends Comparable<T>> {
private class Node {
//结点内容
T val;
//左右孩子
Node left;
Node right;
//初始化
public Node(T val) {
this.val = val;
this.left = null;
this.right = null;
}
}
//根节点
Node root;
//树中结点个数
int size;
public BinarySearchTree() {
this.root = root;
this.size = size;
}
//获取树中结点的个数
public int getSize() {
return size;
}
//判断是否为空树
public boolean isEmpty() {
return this.root == null;
}
}
2、向二分搜索树添加元素(根据二分搜索树的性质)
//向树中添加结点,T是泛型
public void add(T val){
this.root = add(root,val);
}
//在以node为根的二分搜索树中添加val
private Node add(Node node, T val) {
//1、递归终止条件
if(node == null){
return new Node(val);
}
//2、递归操作
if(node.val.compareTo(val) > 0) {
node.left = add(node.left,val);
}else{
node.right = add(node.right,val);
}
return node;
}
3、二分搜索树的查询操作
//查询val是否存在于树中
public boolean find(T val) {
return find(root, val);
}
//从以node为根的二分搜索树中查询内容val
public boolean find(Node node, T val) {
//1、递归终止的条件
if (node == null) {
return false;
}
//2、递归操作
if (node.val.compareTo(val) == 0) {
return true;
} else if (node.val.compareTo(val) < 0) {
return find(node.right, val);
} else {
return find(node.left, val);
}
}
4、二分搜索树的遍历
遍历操作:把所有结点都访问一遍。
前序遍历:对于遍历操作,两棵子树都要顾及
//前序遍历
public List<T> preTraverse(){
List<T> list = new ArrayList<>();
preTraverse(root,list);
return list;
}
//递归方法
private void preTraverse(Node node, List<T> list) {
//1、递归到底的条件
if(node == null){
return;
}
//2、递归操作
list.add(node.val);
preTraverse(node.left,list);
preTraverse(node.right,list);
}
中序遍历:(结果按顺序排列)
//中序遍历
public List<T> middleTraverse(){
List<T> list = new ArrayList<>();
middleTraverse(root,list);
return list;
}
private void middleTraverse(Node node, List<T> list) {
//1、递归终止的条件
if(node == null){
return;
}
//2、递归操作
middleTraverse(node.left,list);
list.add(node.val);
middleTraverse(node.right,list);
}
后序遍历:
//后序遍历
public List<T> afterTraverse(){
List<T> list = new ArrayList<>();
afterTraverse(root,list);
return list;
}
private void afterTraverse(Node node, List<T> list) {
//1、递归终止的条件
if(node == null){
return;
}
//2、递归操作
afterTraverse(node.left,list);
afterTraverse(node.right,list);
list.add(node.val);
}
5、二叉搜索树的层序遍历(广度优先)
//层序遍历---借助队列实现
public List<T> levelTraver(){
List<T> list = new ArrayList<>();
Queue<Node> queue = new LinkedList<>();
if(this.root != null){
queue.offer(this.root);
}
while(!queue.isEmpty()) {
Node temp = queue.poll();
list.add(temp.val);
if (temp.left != null) {
queue.offer(temp.left);
}
if (temp.right != null) {
queue.offer(temp.right);
}
}
return list;
}
6、删除二分搜索树的最大元素和最小元素
1、寻找最大元素和最小元素:
//从二分搜索树中寻找最小元素所在的结点
public Node findMixNode(){
if(root == null){
return null;
}
Node cur = root;
while(cur.left != null){
cur = cur.left;
}
return cur;
}
//使用递归方法:
public Node findMinNodeDG(){
if(root == null){
return null;
}
return findMinNodeDG(root);
}
//以node为根的二分搜索树中查找最小元素所在的结点
private Node findMinNodeDG(Node node){
//1、递归终止的条件
if(node.left == null){
return node;
}
//2、递归操作
return findMinNodeDG(node.left);
}
public Node findMaxnNodeDG(){
if(root == null){
return null;
}
return findMaxNodeDG(root);
}
//以node为根的二分搜索树中查找最大元素所在的结点
private Node findMaxNodeDG(Node node){
//1、递归终止的条件
if(node.right == null){
return node;
}
//2、递归操作
return findMaxNodeDG(node.right);
}
//从二分搜索树中寻找最大元素所在的结点
public Node findMaxNode(){
if(root == null){
return null;
}
Node cur = root;
while(cur.right != null){
cur = cur.right;
}
return cur;
}
2、删除操作:
情况二:非叶子结点
删除操作:
//二分搜索树中删除最小元素所在的结点
public void removeMinNode(){
Node minNode = findMixNode();
if(minNode == null){
return;
}
//进行删除
root = removeMinNode(root);
}
//从以node为根的二分搜索树中删除最小结点
// 返回删除结点后新的二分搜索树的根
private Node removeMinNode(Node node){
//1、递归终止的条件
if(node.left == null){
Node rightNode = node.right;
node.right = null;
this.size--;
return rightNode;
}
//2、递归操作
node.left = removeMinNode(node.left);
return node;
}
7、删除二分搜索树中的结点
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 = minimum(node.right);
successor.right = removeMin(node.right);
successor.left = node.left;
node.left = node.right = null;
return successor;
九、二分搜索树的扩展