数据结构之查找(图片来源,老师PPT)
顺序查找进行遍历元素,进行查找
总计全部比较次数为:1+2+…+n = (1+n)n/2
若求某一个元素的平均查找次数,还应当除以n(等概率), 即: ASL=(1+n)/2 ,时间效率为 O(n)
解释:ASL表示average search length 平均查找长度
public static void main(String[] args) { int[] a=new int[] {5,1,6,9,2,4,8}; System.out.println(linearSearch(a, 9)); } public static int linearSearch(int[] arr,int searchNum) { int res=-1; for(int i=0;i<arr.length;i++) { if(arr[i]==searchNum) { res=i; break; } } return res; }
2.二分查找法
前提,序列有序
平均每个数据的查找时间还要除以n,所以:
public static void main(String[] args) { int[] a=new int[] {1,2,3,4,5,6,7}; System.out.println(linearSearch(a, 3)); } public static int binarySearch(int[] arr,int searchNum) { int low,high,middle; low=0; high=arr.length-1; middle=(low+high)/2; for(int i=0;i<arr.length;i++) { if(searchNum==arr[middle]) { return middle; }else if(searchNum>arr[middle]) { low=middle; middle=(low+high)/2; }else { high=middle; middle=(low+high)/2; } } return -1; }
查找过程可用二叉树描述:每个记录用一个结点表示;结点中值为该记录在表中位置,这个描述查找过程的二叉树称为判定树。
n个元素的表的二分查找的判定树是唯一的,即:判定树由表中元素个数决定。
3.分块查找
这是一种顺序查找的另一种改进方法。 先让数据分块有序,即分成若干子表,要求每个子表中的数值(用关键字更准确)都比后一块中数值小(但子表内部未必有序)。
然后将各子表中的最大关键字构成一个索引表,表中还要包含每个子表的起始地址。
① 对索引表使用二分查找法(因为索引表是有序表);
② 确定了待查关键字所在的子表后,在子表内采用顺序查找法(因为各子表内部是无序表);
查找效率分析:ASL=Lb+Lw
前提:自定义每个区块的数量会影响查找的速度,分块查找在大数据中也有一定的作用,类似大数据的分机器先排序内,再排序外的排序法,只不过这边的区块内部是有序的
4.散列查找(哈希查找)
哈希(Hash)表:即散列存储结构。 散列法存储的基本思想:建立关键码值与其存储位置的对应关系,或者说,由关键码的值决定数据的存储地址。
优点:查找速度极快(O(1)),查找效率与元素个数n无关!
按照计算哈希直接存入计算机地址,Java可以用一个数组空间进行模拟,只要进行计算即可
- 哈希函数的构造方法
直接定址法
Hash(key) = a·key + b (a、b为常数) 优点:以关键码key的某个线性函数值为哈希地址,不会产生冲突. 缺点:要占用连续地址空间,空间效率低。
除留余数法
Hash(key)=key mod p (p是一个整数) 特点:以关键码除以p的余数作为哈希地址。
关键:如何选取合适的p? 技巧:若设计的哈希表长为m,P通常取小于或等于散列表长m的最大素数(p≤m),Java中选用了31,因为31正好是2<<5-1
平方取中法
特点:对关键码平方后,按哈希表大小,取中间的若干位作为哈希地址。
理由:因为中间几位与数据的每一位都相关。 例:2589的平方值为6702921,可以取中间的029为地址。
折叠法
特点:将关键码自左到右分成位数相等的几部分(最后一部分位数可以短些),然后将这几部分叠加求和(舍去进位)作为散列地址。
法1:移位法 ── 将各部分的最后一位对齐相加。
法2:间界叠加法──从一端向另一端沿分割界来回折叠后,最后一位对齐相加。
例:元素42751896, 用法1: 427+518+96=1041 用法2: 427 518 96—> 724+518+69 =1311
5.二叉排序树(又称二叉查找树,中序序列顺序的树)
关于查找:与根节点比较,如果大则右查找,如果小为左查找
关于插入:按照查找进行插入
关于删除,如果是叶子节点直接删除,如果有一个子树,那么删除后把子节点回归,如果有左右两个子树,那么把左子树的最大或者右子树的最小放在原来节点
6.平衡二叉树(AVL树,又称红黑树)(可参考这个博客:https://blog.csdn.net/saasanken/article/details/80796178,关于AVL树)
平衡二叉树又称AVL树,它是具有如下性质的 二叉树:
左、右子树是平衡二叉树; 所有结点的左、右子树深度之差的绝对值≤ 1
即|左子树深度-右子树深度|≤ 1
为了方便起见,给每个结点附加一个数字,给 出该结点左子树与右子树的高度差。这个数字 称为结点的平衡因子balance。这样,可以得到 AVL树的其它性质:
如果在一棵AVL树中插入一个新结点,就有可能造成失衡,此时必须重新调整树的结构,使之恢复平衡。我们称调整平衡过程为平衡旋转。
平衡旋转可以归纳为四类:
优点和缺点:
优点:层数较少,可以尽快查到
缺点:插入时需要旋转多次,这样会小号大量的磁盘IO
7.B-树,B+树,B*树
2-3树(B树的引入)
1)2节点包含一个元素和2个孩子(或者没有孩子)
左子树小于元素,右子树大于元素
2)3节点,包含2个元素,一大一小,三个孩子(或者没有孩子)
左子树节点元素值小于节点元素较小元素值,右节点包含元素大于节点元素较大元素值
3)2-3树所有叶子接待你都在同一层
图2-3树(图片来源:中国大学mooc)
2-3-4树(B树的引入)
1)23节点与23树相似
2)4节点包含3个元素,4个孩子
3)叶子节点也在同一个层级
B-树
B tree,又称B树,B为Balanced
把树中最大的孩子称为B树的阶,一颗M阶的空树,或为满足如下特性的M叉树:
1)树中每个节点至多有M棵子树(有M-1)个关键字
2)若根节点不是终端节点,则至少有2棵子树。(1个关键字)
3)除了根节点以外,非叶子节点至少有【M/2】棵子树。(含有M/2-1个关键字),半满来使空间减少浪费
4)所有非叶子接待你结构都在同一层次上,不带信息。(因为折半查找树中最终的叶子接待你会导致查找失败
关于查找:与二叉排序树类似
因为B树中有多个元素,而且也不用像红黑树一样进行旋转,所有,B树的查找性能优于二叉排序树
弊端:除非重建树,否则无法改变值的最大长度
B+树
常用于数据库和操作系统的文件系统中的一种用于查找的数据结构
B+树的查找性能优于B树
差异:
1)B+树中,具有N个关键字的节点只含有N棵子树,每个关键字对应一棵子树;B树中,N个关键字含有N+1棵子树
2)B+树中,每个节点的关键字个数的范围是[m/2]<=n<=m根节点1<=n<=m,而在B树中,范围比B+树多1
3)每个父亲节点都指向孩子节点的最大关键字
4)B+树中,叶子接待你包含了所有关键字,非叶子接待你中出现的关键字也出现在叶子节点中,叶子节点的指针指向记录,而在B树中,叶子节点的关键字与非叶子节点的关键字加起来才是不重复的
5)B+树中,所有叶子节点构成一个单链表
图B+树(图片来源:中国大学mooc)
B-树和B+树区别
B+树中间层节点存储的是下一层的地址,并没有存储数据。B-树中间层是会存储数据的,所以遍历数据时磁盘IO次数会增多,所有我们常常在数据库和操作系统中选择B+树进行存储数据
B*树
B*树是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)。
![](https://img2018.cnblogs.com/blog/1449595/201906/1449595-20190613161149760-402290719.png)