这里介绍几种基于线性表的查找方法:
- 顺序查找
- 二分查找
- 分块查找
查找的定义是:给定一个值K,在含有n个结点的表中找出关键字等于给定值K的结点。若找到,则查找成功,返回该结点的信息或该结点在表中的位置;否则查找失败,返回相关的指示信息。
1、顺序查找
基本思想:从数据的一端开始查找,比较元素是否与查找元素相同,若有则查找成功,直到另一端结束。既适用于线性表的顺序存储结构,也适用于线性表的链式存储结构,但查找效率较低。
2、二分查找
也称为对半查找
基本思想:将待查找元素与序列中间值进行比较,若相等则找到,大于中值,则可以在右半边继续开始同样的查找工作,小于中值,则在左边;
- 要求数据是有序的,向量作为存储结构,链表是无法实现二分查找的
- 二分查找只适用顺序存储结构。为保持表的有序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。
3、分块查找
也称索引顺序查找,性能介于顺序查找和二分查找
- 基本思想:将数据进行分块,并用一个索引不表存储相关信息;将数据分成若干块,其中前一块的最大值不能大于后一块的最小值,用一个索引表存储每个块中的最大值和块的起始位置,块中的元素可以是无序的,但索引表必须是有序的。
- 查找思路:先在索引表中查找,从而找到数据所在的块,然后在相应的块中的进行顺序查找,找到具体的位置。(基本思路就是先找到数据的范围,从而进行下一
步的查找)
因为各查找方法应用的数据结构不尽相同,因此这里分开对之进行测试训练
顺序查找:
#include <iostream>
using namespace std;
const int N = 10;
int seqsearch(int (&a)[N], int k);
int main()
{
int k, n = 10;
int s[] = {5,6,2,3,9,8,4,1,7,0};
k = seqsearch(s,n);
cout << "元素所在位置:" << k << endl;
}
int seqsearch(int (&a)[N], int k)
{
int i;
for(i = 0; i<N; i++)
{
if(a[i] == k)
return i;
}
return false;
cout << "查找失败!";
}
二分查找,即利用迭代的方式不断进行查找
#include <iostream>
using namespace std;
const int N = 10;
int binsearch(int (&a)[10], int k);
int main()
{
int k, n = 5;
int s[] = {0,1,2,3,4,5,6,7,8,9};
k = binsearch(s,n);
if(k == N)
cout << "查找失败" << endl;
else
cout << "元素所在位置:" << k << endl;
}
int binsearch(int (&a)[10], int k)
{
int mid,left,right;
left =0;
right = N-1;
while (left < right)
{
mid = (left + right) / 2;
if(mid == k)
return mid;
else if(mid < k)
left = mid + 1;
else
right = mid -1;
}
return N; //false
}
分块查找,这里需要一个索引表,因此引用STL中的map来生成索引,这里介绍了map的建立及几种添加元素的方法,还有获取键值的两种方式。
#include <iostream>
#include <map> //利用STL中的map来建立索引表
using namespace std;
const int N = 15;
int blocksort(int (&s)[15], map<int,int> &map1, int k);
int main()
{
int k, n = 5;
int s[] = {1,3,2,0,4,9,6,5,8,7,12,11,10,13,14}; //每5个数为一块
map<int,int>map1; //建立索引表
map1.insert(map<int,int>::value_type(0,4)); //三种map的插入方式,效果相同
map1.insert(pair<int,int>(5,9));
map1.insert(make_pair<int,int>(10,14));
k = blocksort(s,map1,11);
if(k == N)
cout << "查找失败" << endl;
else
cout << "元素所在位置:" << k << endl;
}
int blocksort(int (&s)[15], map<int,int> &map1, int k)
{
int index, blocksize = 5;
int i = 0;
//int a[3]; //获取map索引值的两种方法
//way 1
//a[0] = map1.at(0);
//a[1] = map1.at(5);
//a[2] = map1.at(10);
//way 2 迭代方式
//map<int,int>::iterator it;
//for(i,it = map1.begin(); it != map1.end(); ++it,++i)
// a[i] = it->second;
map<int,int>::iterator it;
for(i,it = map1.begin(); it != map1.end(); ++it,++i){
if(k<=it->second){
index = it->first;
break;
}
}
for(i = index; i<index + blocksize; i++)
{
if(s[i] == k)
return i;
}
return N; //false
}