查找算法-C

查找算法-C

算法的五个特征 : 有穷性、确定性、可行性、输入、输出
算法的设计要求 : 正确性、可读性、健壮性、高效率、低存储

一、顺序查找

从序列的某个位置开始,一直到序列结束,依次比较。

//顺序表
int search(int* arr,size_t len,int key)
{
	for(int i=0; i<len; i++)
    {
        if(arr[i] == key)
            return i;
    }
    return -1;
}
// 从头结点开始,如果找到则返回所在节点的地址,找不到则返回NULL
Node* linear_search(Node* head,int key)
{
	for(Node* n=head; NULL!=n; n=n->next)
    {
        if(n->data == key)
            return n;
    }
    return NULL;
}
二、二分查找

前提:序列有序

思路:

①从序列中间(mid)开始与目标值(key)比较;

②如果相等直接返回 程序结束;

③如果小于key,left=mid+1 如果大于key,right=mid-1;

④如果left<=right 回到①;

//顺序实现
//[left,right]
int binary_search(int* arr, size_t len, int key)
{
    int left = 0 , right = len-1;
    while(left <= right)
    {
        int mid = (left + right) / 2;
        if(arr[mid] == key)
            return mid;
        if(arr[mid] > key)
            right = mid-1;
        if(arr[mid] < key)
            left = mid+1;
    }
    return -1
}
//[left,right)
int binary_search(int* arr, size_t len, int key)
{
    int left = 0 , right = len;
    while(left < right)
    {
        int mid = (left + right) / 2;
        if(arr[mid] == key)
            return mid;
        if(arr[mid] > key)
            right = mid;
        if(arr[mid] < key)
            left = mid+1;
    }
    return -1
}
//递归实现
int _binary_search(int* arr, int left, int right, int key)
{
 	if(left >= right)
        return -1;
 	int mid = (left + right) / 2;
    if(arr[mid] > key)
        return _binary_search(arr,left,mid,key);
    if(arr[mid] < key)
        return _binary_search(arr,mid+1,right,key);
    return mid;
}

int binary_search(int* arr, size_t len, int key)
{
    return _binary_search(arr,0,len,key);
}

优点:速度快:O(log2n)

缺点:要求数据有序、不适用链表

三、哈希查找

​ 在查找数据时需要进行一系列的比较运算,无论是顺序查找、二分查找,都是建立在比较的基础上的,但最理想的查找算法是不经过任何比较,一次存取就能查找到数据,那么就需要在存储位置和它的关键字之间建立一个确定的对应关系,使每个关键字和数据中的唯一的存储位置相对应。在查找时,根据对应关系找到给定的关键字所对应的数据,这样可以不经过比较可以直接取得所查找的数据。

​ 存储位置与关键字之间的对应关系为哈希函数,按这个思想建立的表为哈希表。

//例如:假定有100万个0~255之间的随机数,然后输入一个0~255之间的整数,查询出该数一共出现了多少次。

 for(int i=0; i<1000000; i++)
 {
     arr[i] = rand() % 256;
 }

 // 把数据当值作为数组cnts的下标(把关键字与存储位置相对应),直接定值法,H(key)=key
for(int i=0; i<1000000; i++)
{
    cnts[arr[i]]++;
}

​ 以上是很简单的一个例子,但是可以看出其局限性,比如如果数据范围变为0~1000000,那么这样构建出来的哈希表可能很大,那么就得重新设计哈希函数,但是这样算出来的结果也可能出现重复,因此设计出合适的哈希函数、解决冲突问题是哈希表和哈希查找的关键。

设计哈希函数的方法:
直接定值法:

取关键字的值或某个线性函数作为k哈希地址:H(key) = key 或H(key)=a*key-b,但这种方法对数据有很高的要求。

数字分析法:

假设以关键字key为基数,并且哈希表中可能出现的数字全部知道,取关键字的某几位为哈希地址,例如学号:

​ 1~2系、3~4为专业、5~6为年级、7~9为入学序号,因此H(key)=key%1000。

解决哈希值冲突的方法:
  • 开方地址法
  • 再哈希法
  • 链地址法
  • 创建公共溢出区
哈希查找的优点:

​ 查找速度极快,时间复杂度能达到O(1)。

哈希查找的缺点:

​ 1、局限性比较大,对数据的要求比较高。

​ 2、设计哈希函数麻烦,没具体的设计哈希函数的方法,只是有一些大致的思路。

​ 3、需要建立哈希表,占用了额外的空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值