查找
是在一些有序的或无序的数据元素中,通过一定的方法找出与给定关键字相同的数据元素的过程,即根据给定的某个值在查找表中确定一个关键字等于给定的记录或数据元素。查找是信息处理科学中十分重要的操作。
#define _CRT_SECURE_NO_WARNINGS 1
#define Max 100
#include
using namespace std;
typedef int KeyType;
typedef int InfoType;
typedef int IndexType;
typedef struct
{
KeyType key;//KeyType为关键字数据类型
InfoType otherinfo;//其他域
}SElemType;
class StaticSearchtable
{
private:
SElemType* elem;
int length;
public:
StaticSearchtable()//构造函数,0位留空
{
elem = new SElemType[Max + 1];
length = 0;
}
~StaticSearchtable()//析构函数,释放存储空间
{
delete[]elem;
length = 0;
}
void Create(int n)//创建n个元素的顺序表
{
for (int i = 0; i <= n; i++)
{
cin >> elem[i].key >> elem[i].otherinfo;
}
length = n;
}
int SqSearch(KeyType key);//顺表表查找值等于key的关键字
int BinSearch(KeyType key);//二分查找值等于key的关键字
int IndexSearch(IndexType index[Max], KeyType key, int b);//分块查找值等于key的关键字,b为块数
};
顺序查找的主要思想:
elem[0].key=key
,其作用是防止扫描溢出。key
进行比较,若找到关键字,则查找成功,返回该关键字在顺序表中的下标;否则查找失败,返回0
.int StaticSearchtable::SqSearch(KeyType key)
{
elem[0].key = key;//哨兵位
int i = 0;
for (i = length; elem[i].key != key; i--)//从末端开始向左扫描
{
;//空语句
}
return i;
}
二分查找又称折半查找,它是一种效率较高的查找方法。二分查找要求线性表采用顺序存储结构且元素有序。类似于顺序查找方法,在存储元素时,数组元素第0位留空。
二分查找的主要思想是每次将待查找记录所在的区间缩小一 半。具体步骤如下:设elem[low..high]
是当前的查找区间,首先确定中间点位置mid = [(low+high)/2]
,然后将待查元素的关键字key
值与elem[mid].key
比较:(初始时,令low=1,high=length
)
mid = [(low+high)/2]
key==elem[mid].key
,则查找成功,返回mid
,即该元素在顺序表中的下标。key,则high = mid-1
key>elem[mid].key
,则low = mid+1
low>high
时,查找失败,此时返回0
int StaticSearchtable::BinSearch(KeyType key)
{
int low = 1,high = length;
int mid;
while (low <= high)
{
mid = (low + high) / 2;
if (key == elem[mid].key)
return mid;
else if (key < elem[mid].key)
high = mid - 1;
else
low = mid + 1;
}
return 0;
}
✅二分查找过程可用二叉树来描述,在构造二叉树的过程中,把当前查找区间的中点位置上的元素作为树根,左子表和右子表的元素分别作为根的左子树和右子树。由此递归得到二叉树,通常称描述查找的过程的二叉树为判定树。判定树的形态与表中个数n
相关,与输入示例中的key
值无关。
例如,要找到15个数据元素的有序表中的第
8
个元素仅需比较1
次,找到第4
和第12
个元素需要比较2
次,找到第2,6,10
和14
个元素需要比较3
次;找到第1,3,5,7,9,11,13
和15
个元素需要比较4次。其查找过程如图所示,树中的每个圆圈结点表示表中一个元素,结点中的值表示该元素在表中的位置;圆圈结点表示查找成功,方框结点表示查找失败。若查找失败,则比较过程是一条从判定树的根到某结点的路径,所需关键字比较次数是该路径上圆圈结点的个数。
二分查找分析:
(1).查找成功时平均查找长度:
(2).查找不成功时平均查找长度:
例:给定18个元素的有序表
{2,5,8,10,15,40,42,55,66,70,72,75,80,88,90,100,108,200}
,采用二分查找,试问:
(1).查找长度为4和5的元素个数分别有多少个?
(2).若要查找值为15的数据元素,要经过多少次比较?依次与哪些元素进行比较?
(3).在查找概率相等的情况下,计算查找成功和查找不成功的平均查找长度。
解:第一问可以直接数第四行和第五行元素的个数:分别是8和3
.
第二问数这条路径圆圈结点的个数为比较次数,圆圈内的值为比较的数:
因此,我们需要进行4
次比较,依次与表中的元素66,10,40,15
比较。
第三问,在查找概率相等的情况下,查找成功
的平均查找长度为:
(11+22+43+84+35)/18=32/9
。
查找不成功的平均查找长度为:(413+5*6)/19=82/19
分块查找又称索引顺序查找,它是顺序表查找的一种改进方法,其性能介于顺序查找和二分查找之间。在索引查找方法中,除存储表本身以外,还需存储一个索引表。存储方法如下:
elem[1..n]
均分为b
块,前b-1
块中元素个数为s=[n/b]
,最后一块即b
块的元素个数小于等于s.
index[0..b-1]
,即index[i](0<=i<=b-1)
中存放第i块的最大关键字和该块在表中的初始位置。索引表的数据类型定义:
typedef struct
{
KeyType key;
int link;
}IndexType;
分块查找的算法:
int StaticSearchtable::IndexSearch(IndexType index[Max], KeyType key, int b)
{//b为块数
int low = 0, high = b - 1, mid, i, s;
if (length % b == 0)
s = length / b;
else
s = length / b + 1;
while (low <= high)
{
mid = (low + high) / 2;
if (index[mid].key >= key)
high = mid - 1;
else
low = mid + 1;
}
//在索引表high+1快对应的线性表中顺序查找key
i = index[high + 1].link;
while (i <= index[high + 1].link + s - 1 && elem[i].key != key)
{
i++;
}
if (i <= index[high + 1].link + s - 1)
return i;//查找成功,返回该元素的下标
else
return 0;//查找失败,返回0
}
运行示例:
#define _CRT_SECURE_NO_WARNINGS 1
#define Max 100
#include
using namespace std;
typedef int KeyType;
typedef int InfoType;
typedef struct
{
KeyType key;//KeyType为关键字数据类型
InfoType otherinfo;//其他域
}SElemType;
typedef struct
{
KeyType key;
int link;
}IndexType;
class StaticSearchtable
{
private:
SElemType* elem;
int length;
public:
StaticSearchtable()//构造函数,0位留空
{
elem = new SElemType[Max + 1];
length = 0;
}
~StaticSearchtable()//析构函数,释放存储空间
{
delete[]elem;
length = 0;
}
void Create(int n)//创建n个元素的顺序表
{
for (int i = 0; i <= n; i++)
{
cout << "输入第" << i+1 << "个元素的值和下标:";
cin >> elem[i].key >> elem[i].otherinfo;
}
length = n;
}
int SqSearch(KeyType key);//顺表表查找值等于key的关键字
int BinSearch(KeyType key);//二分查找值等于key的关键字
int IndexSearch(IndexType index[Max], KeyType key, int b);//分块查找值等于key的关键字,b为块数
};
int StaticSearchtable::SqSearch(KeyType key)
{
elem[0].key = key;//哨兵位
int i = 0;
for (i = length; elem[i].key != key; i--)//从末端开始向左扫描
{
;//空语句
}
if (i >= 0)
cout << "该数所在顺序表中的下标为:" << i << endl;
else
cout << "未找到!" << endl;
return 0;
}
int StaticSearchtable::BinSearch(KeyType key)
{
int low = 1, high = length;
int mid;
while (low <= high)
{
mid = (low + high) / 2;
if (key == elem[mid].key)
{
cout << "该数经二分查找下标为:" << mid << endl;
break;
}
else if (key < elem[mid].key)
high = mid - 1;
else
low = mid + 1;
}
if(low>high)
cout << "未找到!" << endl;
return 0;
}
int StaticSearchtable::IndexSearch(IndexType index[Max], KeyType key, int b)
{//b为块数
int low = 0, high = b - 1, mid, i, s;
if (length % b == 0)
s = length / b;
else
s = length / b + 1;
while (low <= high)
{
mid = (low + high) / 2;
if (index[mid].key >= key)
high = mid - 1;
else
low = mid + 1;
}
//在索引表high+1快对应的线性表中顺序查找key
i = index[high + 1].link;
while (i <= index[high + 1].link + s - 1 && elem[i].key != key)
{
i++;
}
if (i <= index[high + 1].link + s - 1)
return i;//查找成功,返回该元素的下标
else
return 0;//查找失败,返回0
}
int main()
{
StaticSearchtable a;
a.Create(8);
a.SqSearch(6);
a.BinSearch(7);
return 0;
}
好啦,关于静态查找表的知识到这里就先结束啦,后期会继续更新学习数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️