算法基础===》==》=》查找

一些基本的查找算法:

  • 静态查找表
  • 哈希表(Hash)查找

静态查找表:

  • 顺序查找
  • 折半查找

顺序查找:

int search_seq(seqTable ST,int key)
{
	int i;
	ST.elem [0].key=key;//"哨兵"
	for(i=ST.len;ST.elem[i].key!=key;i--);//从后往前查找
	/*ST.elem [ST.len ].key=key;--"哨兵"
	for(i=0;ST.elem[i].key!=key;i++);--从前往后查找*/
	if(i<ST.len )
		return i;
	else
		return -1;
}

------》源代码:

#include<iostream>
using namespace std;
#define MAXSIZE 100

//1.结构描述:
typedef struct 
{
	int key;//关键字域
}SElemType;

typedef struct 
{
	SElemType *elem;//数据元素存储空间地址
	int len;//表长度
}seqTable;

//2.顺序查找:
int search_seq(seqTable ST,int key)
{
	int i;
	ST.elem [0].key=key;//"哨兵"
	for(i=ST.len;ST.elem[i].key!=key;i--);//从后往前查找
	/*ST.elem [ST.len ].key=key;--"哨兵"
	for(i=0;ST.elem[i].key!=key;i++);--从前往后查找*/
	if(i<ST.len )
		return i;
	else
		return -1;
}

int main()
{
	seqTable ST;
	int key;
	int index;
	SElemType Data[MAXSIZE]={34,44,43,12,53,55,73,64,77};
	ST.elem =Data;
	ST.len =9;
	cout<<"请输入代查找的关键字:";
	cin>>key;
	index=search_seq(ST,key);
	if(index==-1)
		cout<<"找不到关键字为"<<key<<"的元素!"<<endl;
	else
		cout<<"关键字为"<<key<<"的元素在查找表索引号为:"<<index<<endl;;
	return 0;
}

*ps:顺序查找法既实用于线性表的顺序存储结构,也适用于线性表的链式存储结构。使用单链表作为存储时,在扫描过程中必须从第一个 结点开始往后进行扫描。在顺序查找的过程中可以设置“哨兵“来提高效率。虽然顺序查找的算法结构简单,但效率比较低。特别是当数据量较大时,必须采用更优的查找方法。

折半查找:

int search_Bin(seqTable ST,int key)
{
	int low,high,mid;
	low=0;high=ST.len-1;//置区间初值。
	while(low<=high)
	{
		mid=(low+high)/2;
		if(key==ST.elem[mid].key)
		    return mid;//找到待查元素
		else if(key<ST.elem[mid].key)
			high=mid-1;//继续在前半区查找
		else
			low=mid+1;//继续在后半区查找
	}
	return  -1;//表中不存在待查元素。
}

------》源代码:

#include<iostream>
using namespace std;
#define MAXSIZE 100

//1.结构描述:
typedef struct 
{
	int key;//关键字域
}SElemType;

typedef struct 
{
	SElemType *elem;//数据元素存储空间地址
	int len;//表长度
}seqTable;

//2.折半查找:
int search_Bin(seqTable ST,int key)
{
	int low,high,mid;
	low=0;high=ST.len-1;//置区间初值。
	while(low<=high)
	{
		mid=(low+high)/2;
		if(key==ST.elem[mid].key)
		    return mid;//找到待查元素
		else if(key<ST.elem[mid].key)
			high=mid-1;//继续在前半区查找
		else
			low=mid+1;//继续在后半区查找
	}
	return  -1;//表中不存在待查元素。
}

int main()
{
	seqTable ST;
	int key;
	int index;
	SElemType Data[MAXSIZE]={34,44,43,12,53,55,73,65,77};
	ST.elem =Data;
	ST.len =9;
	cout<<"请输入代查找的关键字:";
	cin>>key;
	index=search_Bin(ST,key);
	if(index==-1)
		cout<<"找不到关键字为"<<key<<"的元素!"<<endl;
	else
		cout<<"关键字为"<<key<<"的元素在查找表索引号为:"<<index<<endl;;
	return 0;
}

*ps: 折半查找,又称二分查找(一般采用递归顺序),它是一种效率较高的查找方式,但二分查找有一定的条件限制:要求线性表必须采用顺序存储结构,并且表中元素必须按关键字有序排列。

哈希表(Hash)查找:

int HashAddr(Student hashTab[],Student stu,int m)
{
	int hr;
	hr=atoi(stu.tel+9)%3;
    return hr;
}
void FillHashTable(Student hashTab[],int n,int m)//n代表了学生的数量
{
   int i,hr;
   for(i=0;i<n;i++)
   {
		hr=HashAddr(hashTab,stu[i],m);
		while(strcmp(hashTab[hr].tel,""))
	 	    hr=(hr+1)%m;
        hashTab[hr]=stu[i];
   }
}
void DispHashTab(Student hashTab[],int m)
{
	int i=0;
   for(i=0;i<m;i++)
	   cout<<hashTab[i].tel<<endl;
   cout<<endl;
}
void HashSearch(Student hashTab[],int m,char tel[])
{
	Student s;int hr;
	strcpy(s.tel,tel);
    hr=HashAddr(hashTab,s,m);
	while(strcmp(hashTab[hr].tel,"")&&strcmp(hashTab[hr].tel,tel))
		hr++;
	if(strcmp(hashTab[hr].tel,""))
		cout<<"Find it!"<<'\t'<<hashTab[hr].name<<'\t'<<hashTab[hr].age<<'\t'<<hashTab[hr].tel<<endl;
	else
		cout<<"Not find!"<<endl;
}

------》源代码:

#include <iostream>
#include <string.h>
using namespace std;

//1.结构描述:
typedef struct{
   char name[10];
   int age;
   char tel[12];
}Student;

//2.初始化结构体:
Student stu[]=
{
	{"Tom",23,"12173873213"},
	{"Rob",21,"13345612284"},
	{"Yin",19,"42332133213"}
};

//3.建立哈希表(Hash)地址:
int HashAddr(Student hashTab[],Student stu,int m)
{
	int hr;
	hr=atoi(stu.tel+9)%3;
    return hr;
}

//4.填充哈希表:
void FillHashTable(Student hashTab[],int n,int m)//n代表了学生的数量
{
   int i,hr;
   for(i=0;i<n;i++)
   {
		hr=HashAddr(hashTab,stu[i],m);
		while(strcmp(hashTab[hr].tel,""))
	 	    hr=(hr+1)%m;
        hashTab[hr]=stu[i];
   }
}

//5.显示哈希表:
void DispHashTab(Student hashTab[],int m)
{
	int i=0;
   for(i=0;i<m;i++)
	   cout<<hashTab[i].tel<<endl;
   cout<<endl;
}

//6.哈希表 搜索 telephonenumber:
void HashSearch(Student hashTab[],int m,char tel[])
{
	Student s;int hr;
	strcpy(s.tel,tel);
    hr=HashAddr(hashTab,s,m);
	while(strcmp(hashTab[hr].tel,"")&&strcmp(hashTab[hr].tel,tel))
		hr++;
	if(strcmp(hashTab[hr].tel,""))
		cout<<"Find it!"<<'\t'<<hashTab[hr].name<<'\t'<<hashTab[hr].age<<'\t'<<hashTab[hr].tel<<endl;
	else
		cout<<"Not find!"<<endl;
}

void main()
{
	//初始化工作:
	Student hashTab[3];
    for(int i=0;i<3;i++)
      strcpy(hashTab[i].tel,"");

	//Hash表的填充与显示
    FillHashTable(hashTab,3,3);
    DispHashTab(hashTab,3);

	//Hash 搜索 telephonenumber
    HashSearch(hashTab,3,"13345612284");
}

*ps:哈希表查找是一种较高级的查找方式,Hash表在海量数据处理中有着广泛应用。

Hash优缺点:
优点:不论哈希表中有多少数据,查找、插入、删除(有时包括删除)只需要接近常量的时间即0(1)【时间复杂度】的时间级。实际上,这只需要几条机器指令。
哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。哈希表不仅速度快,编程实现也相对容易。
如果不需要有序遍历数据,并且可以提前预测数据量的大小。那么哈希表在速度和易用性方面是无与伦比的。

缺点:它是基于数组的,数组创建后难于扩展,某些哈希表被基本填满时,性能下降得非常严重,所以程序员必须要清楚表中将要存储多少数据(或者准备好定期地把数据转移到更大的哈希表中,这是个费时的过程)。

查找Tips:
***无论是顺序查找、二分查找,还是哈希表查找,都有各自的优势。要根据情景特点,选择最合适的查找算法。顺序查找不一定效率最低,有时甚至会优于二分查找,所以具体情况要具体应对。

猜你喜欢

转载自blog.csdn.net/qq_43595030/article/details/91040637
今日推荐