基本概念介绍
树(tree)抽象的数据类型。
节点、根、叶子。
节点的分支大于2,称为多路树。
每个节点【最多】有两个子节点称为二叉树。
Java中的对象,可以看做节点。
引用,看做树干。
所经过的节点的顺路排列称为:路径。
根节点,子节点,叶节点【没有子节点的的节点】
任何一个节点都可看做是一个子树。
根节点是一层,根的子节点就是二层,子节点的子节点是三层…以此类推。
深度,第一层的节点深度是0,第二层的节点深度为1。
层数-1==深度。
从下往上看是高度。 底层高度为0,逐层+1。
二叉树:
二叉搜索树:若左子树不为空,左子树上的所有节点的值都小于根节点得值。
若右子树不为空,右子树上的所有节点的值都大于根节点得值。
它的左右子树分别成为二叉排序树。
中序遍历:左、根、右。【最常用】
前序遍历:根、左、右。
后序遍历:左、右、根。
【以根首要】
可以根据中序遍历对二叉搜索树遍历进行排序,最小的值就是第一个,因为左节点永远是最小最先输出,右节点最大最后输出。
二叉搜索树–删除节点的三种情况:
1.删除叶子结点。【直接删除就可以,将该节点的父节点的引用改为null即可】
2.删除只有一个子节点的节点。【删除该节点,需要该节点的父节点的引用指向该节点的子节点】
3.删除有两个子节点的节点【大于该节点的最小节点称为,后继节点,父节点的引用指向后继节点,被删除节点的其他子节点就跟在后继节点的引用上】
二分查找算法,要求数组必须是有序的。
最大的缺点就是在要求上:强制依赖有序数组,如果无序则还需要排序。
同样数组也具有缺陷:
1.在数组进行增删时,需要后面的全部节点都移动。
2.数组的长度是不变的。只能通过新建一个length+1的数组,并将原数组进行拷贝,再加入新节点。
无法灵活的插入和扩容。
public class TwoTreeSuanFa {
public static void main(String[] args) {
int[] arr =new int[]{1,2,5,6,7,8,9,15,16,19,20};
int data=20;
System.out.println(binarySearch(arr,data));
}
/**
* 二分法查找
* @param arr 有序数组
* @param data 查找的数据
* @return index 下标,未查找到时返回-1
*/
public static int binarySearch(int[] arr, int data){
int low=0;
int height =arr.length-1;
int num=1;
while (low<=height){
int mid = low+(height-low)/2;
if (arr[mid]<data){
System.out.println("第"+num+"次查找,中间数下标为"+mid+",该数为"+arr[mid]);
low=mid+1;
}else if(arr[mid]==data){
System.out.println("第"+num+"次查找,中间数下标为"+mid+",该数为"+arr[mid]);
System.out.println(num);
return mid;
}else if(arr[mid]>data){
System.out.println("第"+num+"次查找,中间数下标为"+mid+",该数为"+arr[mid]);
height=mid-1;
}
num++;
}
return -1;
}
}
链表:
使用链表能够弥补数组的缺陷。但是链表也有自己的缺陷,就是查询效率低于数组,数组只需要知元素下标,就能够定位到数组的位置。
单向链表:每个元素都保留该元素以及向下元素的指针(引用)。
双向链表:每个元素都保留该元素以及向上元素的指针和向下元素的指针。
二叉搜索树就和链表比较相似。
时间复杂度
二叉搜索树就是二分算法衍生出的数据结构,能够比较合理的解决有序数组的问题。
二叉搜索树时间复杂度:每次都能排除一半:相当于N/(2的k次方:2^k)。肯定是大于等于1。
这里时间复杂度是按照最坏情况计算,所以就是N/2k=1。2k=N。K=log2(N)。
因此二分查找算法的时间复杂度度就是O(log2(N))—> O(logN)。
同样二叉搜索树也具有致命的缺陷。根节点左节点(并且所有左节点都是其父节点的左子节点)有很多,右节点只有一个。
这样的二叉搜索树就退化成了一个链表,此时查找的时间复杂度就变成了O(N)。效率极低。
怎么解决这样的问题呢?最好能够动态的实现二叉搜索树。
在每次插入元素时,能够尽可能的左右保持平衡。
于是就产生了平衡树。平衡树具有二叉树的全部特性,同时每个节点的左子树和右子树的高度差最多等于1。
这样不就可以解决问题了吗?为什么还会有红黑树呢?
因为平衡树的要求太高,在插入时会很耗费性能。
于是才有红黑树,对平衡树进行折中。