第七章我们主要是学习了查找,是在前面的基础上对查找进行优化。
一、基本概念
查找表:由同一类型的数据元素或记录构成的集合。(完全松散)
关键字:根据给定的某个值,在查找表中确定一个其关键字等于给定值的记录或数据元素。
动态查找表和静态查找表:若在查找的同时对表做修改操作(如插入或删除),则相应的表称为动态查找表,否则称为静态查找表。
平均查找长度(ASL):和给定值进行比较的关键字个数的期望值。
二、查找方法
1. 顺序查找
思路:从表的一端开始,顺序扫描表,依次将扫描到的结点关键字和给定值(假定为a)相比较,若当前结点关键字与a相等,则查找成功;若扫描结束后,仍未找到关键字等于a的结点,则查找失败。
顺序查找也是最普通的一种方法,我们刚开始学习的时候几乎都会用这种查找方法,也就是从头开始,一个一个地进行比较,所以这也是效率最低的一个方法。
适用于线性表的顺序存储结构和链式存储结构。
算法实现:
int sequential_search(int *a, int n, int key) { int i; for (i=1; i<=n; i++) { if (a[i] == key) return i; } return 0; }
平均查找长度=(n+1)/2
顺序表查找优化:
int sequential_search(int *a, int n, int key) {//有哨兵的顺序查找 int i; a[0] = key; i=n; while(a[i]!=key) { i--; } return i; }
2、 折半查找(二分查找)
思路:在有序表中,取中值记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功,若给定值小于中间记录的关键字,则在中间记录的作伴去继续查找,若大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域记录,查找失败为止。
算法实现:
int bitnary_seqarch(int *a, int n, int key) { int low, high, mid; low=1; high=n; while(low<=high) { mid=(low+high)/2; if(key<a[mid]) high = mid-1; else if(key>a[mid]) low=mid+1; else return mid; } return 0; }
3、分块查找
思路:二分查找表使分块有序的线性表和索引表(抽取各块中的最大关键字及其起始位置构成索引表)组成,由于表是分块有序的,所以索引表是一个递增有序表,因此采用顺序或二分查找索引表,以确定待查结点在哪一块,由于块内无序,只能用顺序查找。
三、树表的查找(对于动态查找表)
在这一节主要是介绍了二叉排序树,平衡二叉树,B - 树和B+树,这也是从一开始的二叉排序树不断进行优化,一直到现在应用最多的B+树,也是最有现实意义的方法。
B+树是应文件系统所需而出的一种B树的变形树,但从严格意义上来讲,它其实已经不是第六章定义的树了,在B树中,每一个元素在该树上只出现一次,有可能在分支结点,也有可能在叶子结点。而在B+树中,出现在分支结点中的元素会被当做它们在该分支结点位置的中序后继者中在此列出。另外,每个叶子结点都会保存一个指向后一叶子结点的指针。B+树适合带有范围的查找,比如查找我们学校18~20岁是我学生人数,我们可以通过从根结点出发找到第一个18岁的学生,然后在叶子结点顺序查找符合范围的所有记录。
四、总结
这一章我们都是围绕查找来学习的,首先当然是需要弄清楚一些基本概念,然后再是掌握哪些基本方法。查找,在我们的生活中也经常会用到,所以实际性比较高。
最后就是临近期末,所以要开始准备复习了,希望能抓紧时间将学过的知识好好复习一遍。