参考: https://www.cnblogs.com/yw09041432/p/5908444.html
七大查找算法:
- 1. 顺序查找:顺序查找适合于存储结构为顺序存储或链接存储的线性表,时间复杂度为O(n)
- 2. 二分查找:元素必须是有序的,如果是无序的则要先进行排序操作。
- 3. 插值查找:基于二分查找算法,将查找点的选择改进为自适应选择,mid=low+(key-a[low])/(a[high]-a[low])*(high-low),适合表长较大,而关键字分布又比较均匀的查找表
- 4. 斐波那契查找:二分查找的一种提升算法,通过运用黄金比例的概念在数列中选择查找点进行查找,要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1;开始将k值与第F(k-1)位置的记录进行比较(及mid=low+F(k-1)-1)。如果>,low=mid+1,k-=2;如果<,high=mid-1,k-=1。
5. 树表查找:
(1)二叉查找树与平衡二叉树(AVL)
(2)平衡查找树之2-3查找树(2-3 Tree) :其实和B树很像,只不过限定了m=3,节点只有1个或者2个key
效率:
(3)平衡查找树之红黑树(Red-Black Tree)
2-3树实现起来比较复杂,于是就有了一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree)。
基本思想:红黑树的思想就是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息。红黑树中将节点之间的链接分为两种不同类型,红色链接,他用来链接两个2-nodes节点来表示一个3-nodes节点。黑色链接用来链接普通的2-3节点。特别的,使用红色链接的两个2-nodes来表示一个3-nodes节点,并且向左倾斜,即一个2-node是另一个2-node的左子节点。这种做法的好处是查找的时候不用做任何修改,和普通的二叉查找树相同。
红黑树是一种具有红色和黑色链接的平衡查找树,同时满足:
- 红色节点向左倾斜
- 一个节点不可能有两个红色链接
- 整个树完全黑色平衡,即从根节点到所以叶子结点的路径上,黑色链接的个数都相同。
下图可以看到红黑树其实是2-3树的另外一种表现形式:如果我们将红色的连线水平绘制,那么他链接的两个2-node节点就是2-3树中的一个3-node节点了。
红黑树的特性:
- (1)每个节点或者是黑色,或者是红色。
- (2)根节点是黑色。
- (3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
- (4)如果一个节点是红色的,则它的子节点必须是黑色的。
- (5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
下图是一个典型的红黑树,从中可以看到最长的路径(红黑相间的路径)是最短路径的2倍:平均高度大约为logn
红黑树这种数据结构应用十分广泛,在多种编程语言中被用作符号表的实现,如:
- Java中的java.util.TreeMap,java.util.TreeSet;
- C++ STL中的:map,multimap,multiset;
- .NET中的:SortedDictionary,SortedSet 等。
(4)B树和B+树(B Tree/B+ Tree)
平衡查找树中的2-3树以及其实现红黑树。2-3树中,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。
所以B树其实是对2-3树的扩展
B+树是对B树的变形:
B+ 树的优点在于:
- 由于B+树在内部节点上不好含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率。
- B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
但是B树也有优点,其优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。
B/B+树常用于文件系统和数据库系统中,它通过对每个节点存储个数的扩展,使得对连续的数据能够进行较快的定位和访问,能够有效减少查找时间,提高存储的空间局部性从而减少IO操作。它广泛用于文件系统及数据库中,如:
- Windows:HPFS文件系统;
- Mac:HFS,HFS+文件系统;
- Linux:ResiserFS,XFS,Ext3FS,JFS文件系统;
- 数据库:ORACLE,MYSQL,SQLSERVER等中。
树表查找总结:
二叉查找树平均查找性能不错,为O(logn),但是最坏情况会退化为O(n)。在二叉查找树的基础上进行优化,我们可以使用平衡查找树。平衡查找树中的2-3查找树,这种数据结构在插入之后能够进行自平衡操作,从而保证了树的高度在一定的范围内进而能够保证最坏情况下的时间复杂度。但是2-3查找树实现起来比较困难,红黑树是2-3树的一种简单高效的实现,他巧妙地使用颜色标记来替代2-3树中比较难处理的3-node节点问题。红黑树是一种比较高效的平衡查找树,应用非常广泛,很多编程语言的内部实现都或多或少的采用了红黑树。
除此之外,2-3查找树的另一个扩展——B/B+平衡树,在文件系统和数据库系统中有着广泛的应用。
---------------------------------------------------------------------------------------------------------------------------------------------------
6. 分块查找:分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
7. 哈希查找:散列查找(直接定址),哈希函数构造方法(尽量减少冲突)+解决冲突的方法(开放定址和拉链法)
以空间换时间,map的本质就是Hash表
------------------------------------------------------------------------------------------
字符串匹配算法:KMP(从O(mn)降低到O(m+n))
KMP如何借助next数组移位
道理其实很简单,如果目标串和模式串的字符匹配,那么就同时移动两者的下标;如果不能匹配,就使用next数组来获得移动的数目。但编程方法实现的话,next数组我们需要再修改一下,这样就能够直接获得当前失配位置应当对应的新的模式串字符下标(因为我们关注的是在失配字符之前有几个匹配的字符)。
所以,next数组来对每个位置找到最长公共前缀
适合主串和子串有很多部分匹配的情况
大致求next数组的代码:注意这里是设置最开始是-1和0,也可以设置0,1
void kmp(const string& match, const string& pattern) { int posP = -1, posM = -1, lenM = match.length(), lenP = pattern.length(); while (posP < lenP && posM < lenM) { if (posP == -1 || pattern[posP] == match[posM]) { posP++; posM++; } else { posP = nextArr[posP]; } } }