欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

常用查找算法

程序员文章站 2022-07-12 14:50:24
...

一、顺序搜索

      顺序查找是在一个已知无(或有)序队列中找出与给定关键字相同的数的具体位置。顺序查找适合小规模的数据
原理
从序列的第一个元素开始,依次与关键字进行比较,直到找到目标关键字或者查找失败。
1、从表中的第一个元素开始,依次与关键字比较。
2、若某个元素与关键字匹配,则查找成功。
3、若直至最后一个元素还未匹配关键字,则查找失败。

时间复杂度
      顺序查找平均关键字匹配次数为表长的一半,其时间复杂度为O(n)。
      插入数据时可在O(1)时间内完成。但是对于数据规模较大时,效率较低。

实现

int search(int a[],int n,int target)
{
	int i;
	for(i=0;i<n;i++){
	   if(target==a[i])
		return i;
	}

	return -1;
}

二、分块搜索
      分块查找又称索引顺序查找,是顺序查找和折半查找的一种改进方法;分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。

原理
      将n个数据元素“按块有序”划分为m块(m<n)。每一块中的结点不必有序,但块与块之间必须“按块有序”。即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素都必须小于第3块中的任一元素,...。

查找步骤

1、先选取各块中的最大关键字构成一个索引表;
2、先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中
3、在已确定的块中用顺序法进行查找


实现

#include<stdio.h>

struct number{  //定义块的结构
	int key;
	int start;
	int end;
}array_table[4];

int blocks_search(int a[],int num)
{
	int i,j;
	i=0;
	while(num>array_table[i].key && i<4)
		i++;
	if(i>=4)
		return 0;
	j=array_table[i].start;
	for(;num!=a[j] && j<=array_table[i].end;j++);
	if(j>array_table[i].end)
		j=0;
	return j;
}

int main()
{
	int i,j,key,a[16];
	j=0;
	
	printf("please input the number:\n");
	for(i=1;i<16;i++)
		scanf("%d",&a[i]);
	
	for(i=1;i<=3;i++){
		array_table[i].start=j+1;//确定每个块范围的起始值
		j=j+1;
		array_table[i].end=j+4;  //确定每个块范围的结束值
		j=j+4;
	    array_table[i].key=a[j]; //确定每个块范围中元素的最大值
	}
	
	printf("please input the number which do you want to search:\n");
	scanf("%d",&key);  
	k=blocks_search(key,a);
	if(k!=0)
		printf("success the position is:%d\n",k);
	else
		printf("no found!");
}


三、哈希表

哈希表查找是先利用哈希表存储元素,再利用哈希特性进行查找的一种方法。
原理
       使用一个下标范围比较大的数组来存储元素。设计一个哈希(散列)函数,使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;简单理解为按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方。

函数构造
设h(k)表示关键字k的元素所对应的函数值。
1、除余法:
选择一个正整数p,令h(k)=k mod p。这里p选取的是较大的素数比较好。
2、如果关键字的位数比较多,超过长整型范围而无法直接运算,可以选择其中数字分布比较均匀的若干位,所组成的新的值作为关键字或者直接作为函数值。

实现

typedef struct ListNode{
	const char *value;
	struct ListNode *next;
}ListNode;

typedef struct HashTable{
	struct ListNode **list;
	int tableSize;
}HashTable;

ListNode* Find(const char *key,HashTable* H)
{
	ListNode* p;
	ListNode* L;
	L=H->list[hash(key,H->tableSize)];
	p=L->next;
	while(p!=NULL && p->value!=key)
		p=p->next;
	return p;
	
}
void Insert(const char *key,HashTable* H)
{
	ListNode* p,*temp;
	ListNode* L;
	p=Find(key,H);
	if(p==NULL){
		temp=(ListNode*)malloc(sizeof(ListNode));
		if(temp==NULL)
			printf("out of space");
		else{
			L=H->list[hash(key,H->tableSize)];
			temp->next=L->next;
			temp->value=key;
			L->next=temp;
		}
	}
}

四、二分搜索

       二分查找也称折半查找(Binary Search),是一种效率较高的查找方法。但是,二分查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

实现

int binary_search(int a[],int target,int n)  
{  
    int low,high,mid;  
    low=0,high=n;  
    while(low<=high){  
        mid=low+(high-low)/2;  
        if(a[mid]<target)  
           low=mid+1;  
        if(a[mid]>=target)  
           high==mid-1;  
    }  
    return low;  
}  

五、二分搜索树

通常用平衡树实现C++标准模板库中的set模板。