二叉排序树
定义:左子树小于根节点,右子树大于根节点,不一定是平衡树。
散列表的插入查找删除基本已经做到了O(1)但好多时候还用二叉查找树原因:
(1)本身底层结构使然 :散列表底层是数组,且采用散列函数确定位置,散列函数等的设计所要考虑因素多,扩容缩容处理比较复杂,由于散列函数以及哈希冲突的存在,速度不一定优于二叉树。而二叉树采用树的结构,随用随申请空间,且只需要考虑平衡性的问题,较为成熟,且使用红黑树查找删除等操作的固定复杂度为logn
(2)不同场景应用:散列表无序,而二叉树是有序的结构,中序遍历输出一个有序的数据。
具体实现:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
TreeNode(int val){
this.val=val;
}
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
//二叉查找树
public class BinarySearchTree {
private static TreeNode tree;
public static void main(String[] args) {
BinarySearchTree a=new BinarySearchTree();
a.init();
a.delete(1);
System.out.println(a.find(4));
System.out.println(a.searchMin().val);
System.out.println(a.searchMax().val);
a.preOrderTraversalRecursive(tree);
System.out.println();
a.preOrderTraversal();
a.midOrderTraversalRecursive(tree);
System.out.println();
a.backOrderTraversalRecursive(tree);
System.out.println();
System.out.println(a.sequenceNumberRecursive(tree));
}
public void init() {
int[] m= {2,5,4,3,6,9,1};
for(int i=0;i<m.length;i++) {
insert(m[i]);
}
}
public boolean find(int data){
TreeNode p=tree;//保证改变后原本的指针没变,还在根节点,便于后续操作
while(p!=null) {
if(p.val<data) {
p=p.right;
}
else if(p.val>data) {
p=p.right;
}
else {
return true;
}
}
return false;
}
public void insert(int data){
TreeNode p=tree;
if(tree==null) {
tree=new TreeNode(data);
return ;
}
while(p!=null) {
if(data>p.val) {
if(p.right==null)
{
p.right=new TreeNode(data);
return;
}
else
p=p.right;
}
else {//data<p.val
if(p.left==null) {
p.left=new TreeNode(data);
return;
}
else
p=p.left;
}
}
}
public void delete(int data) {
//删除分为三种情况,(1)待删除结点无子节点,只需删除本身以及指向他的引用(2)有一个子节点,只需把子节点放到删除结点的位置
//(3)两个子节点,需要找到该点右子树的最左结点,因为最左结点是根节点右边最小的一个,同时也比根节点左边的都大
TreeNode p=tree;
TreeNode pp=null;//指向要删除结点的父节点
while(p!=null&&p.val!=data) {//寻找待删除结点p
pp=p;
if(data>p.val) {
p=p.right;
}
else {
p=p.left;
}
}
if(p==null) {
return;//不存在这个点
}
if(p.left!=null&&p.right!=null) {//左右子树都有
TreeNode minpp=p;
TreeNode minp=p.right;
while(minp!=null) {//最左结点get
minpp=minp;
minp=minp.left;
}
p.val=minp.val;//p的数据赋值为minp的
//删除结点minp???
//p=minp;
//pp=minpp;//这个是放到后面一起处理了,也可以直接赋值为null。
minpp.left=null;
}
//仅有一个子树或者是叶节点
TreeNode child=null;
if(p.left!=null)
child=p.left;
else if(p.right!=null)
child=p.right;
else;
if(pp==null) {//删除的是根节点
tree=child;
}
else if(p==pp.left)//左子树
pp.left=child;
else //左子树
pp.right=child;
}
//求二叉树的最小结点
public TreeNode searchMin() {
if(tree==null)
return tree;
TreeNode p=tree;
while(p.left!=null) {
p=p.left;
}
return p;
}
//求二叉树的最大结点
public TreeNode searchMax() {
if(tree==null)
return tree;
TreeNode p=tree;
while(p.right!=null) {
p=p.right;
}
return p;
}
//递归实现先中后序遍历
public void preOrderTraversalRecursive(TreeNode p) {
if(p==null)
return;
System.out.print(p.val+" ");
preOrderTraversalRecursive(p.left);
preOrderTraversalRecursive(p.right);
}
public void midOrderTraversalRecursive(TreeNode p) {
if(p==null)
return;
midOrderTraversalRecursive(p.left);
System.out.print(p.val+" ");
midOrderTraversalRecursive(p.right);
}
public void backOrderTraversalRecursive(TreeNode p) {
if(p==null)
return;
backOrderTraversalRecursive(p.left);
backOrderTraversalRecursive(p.right);
System.out.print(p.val+" ");
}
//求二叉树层数
public int sequenceNumberRecursive(TreeNode p) {
int a=0;
if(p==null)
return 0;
a=Math.max(sequenceNumberRecursive(p.left),sequenceNumberRecursive(p.right))+1;
return a;
}
}