数据结构之查找算法

算法是找工作笔试面试的必考点,一般算法分为数值算法非数值算法

数值算法一般用于工程的计算,比如研究导弹方向之类的工程

非数值算法一般用于系统编程,比如研究程序的运行效率之类的编程

这篇文章谈一谈查找算法,即在一系列数据中去查找我们所要的数据。

线性查找
所谓线性查找,即从头开始,一次将每一个元素与查找目标进行比较,或找到目标,或找不到目标

线性查找的平均时间复杂度为O(N),对被查找的数据没有任何规律性的要求

下面是一个简单的线性查找的接口:

size_t line_find(int data[], size_t size, int key) //data为我们已知的数组,size为数组大小,key为我们要查找的元素
{
    size_t i;
    for(i = 0; i < size; i++)
    {
        if(data[i] == key)
        {
            return i;
        }
    }
    return -1;
  }
二分法查找
假设表中元素按照升序排列,我们先找中间元素,然后利用中间元素将表划分为前后两个子表,就这样循环查找。

二分法查找的平均时间复杂度为O(logN),被查找的数据必须为有序的,如果我们先对其进行排序,那么数组的下标位置会被改变,不利于我们的查找,然后排序也会浪费我们一部分时间

下面是一个实现二分法查找的接口:

size_t half_find(int data[], size_t size, int key) //data为数组,size为数组大小,key为要查找的元素
{
    int left = 0;
    int right = size - 1;
    while(left <= right)
    {
        int mid = (left + right) / 2;
        if(key < data[mid])
        {
            right = mid - 1;
        }
        else if(data[mid] < key)
        {
            left = mid + 1;
        }
        else
        {
            return mid;
        }
    }
    return -1;
}       

下面给个测试用例:

int main(int argc, char **argv)
{           
    srand(time(NULL));
    int data[10];
    size_t i;
    size_t size = sizeof(data) / sizeof(data[0]);
    for(i = 0; i < size; i++)
    {
        printf("%d ", data[i] = /*rand() % 100*/i);
    }
    printf("\n");
    printf("查找目标:");
    int key;
    scanf("%d", &key);
    printf("查找结果:");
    //i = line_find(data, size, key);  //线性查找
    i = half_find(data, size, key);  //二分法查找
    if(i == (size_t) - 1)
    {
        printf("失败!\n");
    }
    else
    {
        printf("[%u] %d\n", i, data[i]);
    }
    return 0;
}

下面是一个关于查找算法的题目:

设计一个查找算法函数,返回匹配元素的下标
数组:1 2 8 9 2 4 9 12 4 7 10 13 6 8 11 15

一般人一看就以为这是用线性查找方法,但是其实这道题考的是二分法的思想。

这个数组的规律可以看出,每四个数字是按照顺序排列的,也就是可以使用我们的二分法查找。然后用矩阵的形式将这个数组表达出来:

1 2  8  9
2 4  9 12
4 7 10 13
6 8 11 15

每行每列都是按升序排列的,然后每个右上角的数即可作为中间值来使用二分法。

程序:

#include <stdio.h>

size_t find(int data[], int rows, int cols, int key)//定义行号和列号确定下标
{
    if(!data || !rows || !cols)
    {
        return -1;
    }
    int row = 0;
    int col = cols - 1;
    while(row < rows && col >= 0)
    {
        size_t i = row * cols + col;
        if(key < data[i])
        {
            --col;
        }
        else if(data[i] < key)
        {
            ++row;
        }
        else
        {
            return i;
        }
    }
    return -1;
}

int main(int argc, char **argv)
{
    int data[] = {1, 2, 8, 9, 2, 4, 9, 12, 4, 7, 10, 13, 6, 8, 11,
    15};
    int j = 0;
    for(j = 0; j < 16; j++)
    {
        printf("%d ", data[j]);
    }
    printf("\n");
    int key;
    printf("请输入要查找的数:");
    scanf("%d", &key);
    size_t i = find(data, 4, 4, key);
    if(i == (size_t)-1)
    {
        printf("查找失败!\n");
    }
    else
    {
        printf("[%u] %d\n", i, data[i]);
    }
    return 0;
}

查找算法很基础,下一篇文章将学习经典的排序算法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值