数据结构与算法之四 搜索算法

简介: 数据结构与算法之四 搜索算法

视频课堂https://edu.csdn.net/course/play/7621


目标


在本章中,你将学习: 使用线性搜索技术搜索数据和二叉搜索技术搜索数据


线性搜索:

是最简单的搜索方法, 也称作顺序搜索, 包括将用该条目逐一与列表中的条目进行比较, 线性搜索通过比较所需的元素与列表中第一个元素进行。

如果值不匹配:


      则所需的元素将与列表中的第二个元素作比较。

如果值还是不匹配:

    则所需的元素将与列表中的第三个元素作比较。

这个过程将一直持续下去,直到:

   找到所需的元素或到达列表的未尾为止。

使用线性搜索算法编写一个算法以搜索 员工记录列表 中给定的员工的工号:

1.  读取要搜索的工号     ( 首先确定你要找的工号 )

2. 设置 i = 0   n 是数组的最大值下标 ( 上界 )

3. 重复步骤 4 直到 i > n 或 arr[i] = employee ID

4. i 值增加 1

5. 如果 i > n:

          显示 “ 未找到 ”

    否则

          显示 “ 已找到 ”

搜索算法的效率是由算法的运行时间决定的。


在最佳情况下:

元素位于列表的第一个位置。

比较次数为 1 。

线性搜索的最佳的效率是 O(1) 。

在最差情况下:

元素 位于列表中最后一个位置或者它根本不存在于该列表中 。

比较次数为元素的数。

线性搜索最差的效率是 O(n) 。

在平均情况下:


线性搜索的平均比较数由最佳和最差搜索中的平均比较数决定 。

线性搜索的平均效率是 1/2(n + 1) 。

课间思考


您要在一个包含5000个元素的数组中应用线性搜索来搜索一个元素,如果在搜索的最后,您发现该元素不在该数组中,则为了在该给定的列表中搜索所需的元素您要进行多少次的比较?


答案:

5,000

问题描述:


编写一个在含有最多 20 个数的数组中使用线性搜索算法搜索一个给定数的程序, 如果要搜索的元素在列表中出现多次,则该程序应该显示第一次出现的位置,还 应该显示所作的比较总数。

二叉搜索算法:

用于搜索大列表, 以十分少的比较来搜索数据, 只要要搜索的列表已经排序,则可以使用二叉搜索算法

考虑一个示例。

您要在以字母顺序排列的电话目录中搜索名字 Steve 。

要使用二叉搜索算法搜索名字 Steve :

在中间打开电话目录以确定哪一半包含该名字。

在那一半的中间再打开以确定哪一半包含该名字。

重复此过程直到找到所需的名字为止。

二叉搜索每次就减少了一半的搜索页数。

编写一个算法以实现二叉搜索算法。

1. 接受要搜索的元素 ( 确定要查找的值 )

2. 设置 lowerbound = 0

3. 设置 upperbound = n – 1

4. 设置 mid = (lowerbound + upperbound)/2

5. 如果 arr[mid] = 所需元素:

a. 显示 “ 已找到 ”

b. 转到步骤 10

6. 如果所需元素 < arr[mid]:

a. 设置 upperbound = mid – 1

7. 如果所需元素 > arr[mid]:

a. 设置 lowerbound = mid + 1

8. 如果 lowerbound <= upperbound:

a. 转至步骤 4

9. 显示 “ 未找到 ”

10. 退出

在二叉搜索算法中的每个步骤中,搜索区域都减半。

该算法的最好情况是如果要搜索的元素正好位于列表的最中间的位置:

此情况的比较数为 1 。

在最差情况下,列表中未找到所需元素 :

在第一次对分后,搜索空间减少到 n/2 个元素,其中 n 是原始列表中的元素数。

第二次对分后,搜索空间减少到 n/4 ,即 n/22 个元素。

经过第 i 次对分后,搜索空间减少到 n/2i  元素。

课间思考

在 ___________ 搜索算法中,您从列表的一端开始并且扫描整个列表直到找到所需 项或到达列表的末尾为止。

答案:


线性

要执行 __________ 搜索算法,列表应该是经排序的。

答案:

二叉

问题描述:

编写一个程序,它使用二叉搜索在含有最多 20 个元素的数组中搜索一个数,假设 数组元素是以升序输入的。如果数组中有多个要搜索的数,则发现一个匹配后搜 索就停止了。程序还应该显示所作的比较总数。

小结

在本章中,你已经学到:

线性搜索的最佳效率是 O(1) ,最差效率 O(n) 。

要应用二叉搜索算法,应该确保要搜索的列表是排过序的。

二叉搜索的最佳效率是O(1),最差效率是O(log n)

/*从8个数中查找数字*/
using System;
class Ban
{
  public static void Main(string[]args)
  {
    //int []arr={8001,8002,8003,8004,8007,8010,8005,8009}; //定义有8个整数的数组   
    Console.WriteLine("请输入您的工号个数:");
    int n; //n为数组的上界
    n=Convert.ToInt32(Console.ReadLine());  //n就是数组的长度(个数)
    int []arr=new int[n];   //定义有10个数字的数组
    for(int j=0;j<n;j++)
    {
      Console.Write("请输入第"+(j+1).ToString()+"个数:");
      arr[j]=Convert.ToInt32(Console.ReadLine());
    }   
    //3.重复步骤 4 直到 i > n 或 arr[i] = id 才退出.
   char ch='y'; //定义我们不断查找的条件,如果为y|Y,则一直查找;n|N:则退出查找.
   while((ch=='y')||(ch=='Y'))
   {
    Console.WriteLine("请输入您要查找的数字:");
    int id=Convert.ToInt32(Console.ReadLine()); //定义要查找的数据元素  
    int lowerbound=0;
    int upperbound=n-1;
    int mid=(lowerbound+upperbound)/2;  //中间值下标
    //13   
    while(lowerbound<=upperbound) //实现找合适的中间值索引
    {
      if(id<arr[mid])
        upperbound=mid-1;
      else
        lowerbound=mid+1;
      mid=(lowerbound+upperbound)/2;  
      Console.WriteLine("low:"+lowerbound+"mid:"+mid+"upper:"+  upperbound);  
    }
    //针对找到数据元素,代码
        Console.WriteLine(arr[mid]);
    if(id==arr[mid])
        Console.WriteLine("ok");
    else    
      Console.WriteLine("没有找到....");
    Console.WriteLine("您是否继续查找,是(y|Y),否(n|N):");
    ch=Convert.ToChar(Console.ReadLine());  
  }//不断查找结束   
  }
}

/*使用二叉搜索在含有最多20个元素的数组中搜索一个数,假设数组是以升序输入的。如果数组中有多个要搜索的数,则发现一个匹配后搜索就停止了。
程序还应该显示所作的比较总数。
*/
using System;
class BinarySearch
{
  static void Main(string[]args)
  {
    int[]arr=new int[20]; //要搜索的数组
    int n;  //数组中的元素数
    int i;  //获取在数组中存储的元素数
    while(true)
    {
      Console.Write("请输入数组的元素个数:");
      string s=Console.ReadLine();
      n=Int32.Parse(s);
      if((n>0)&&(n<=20))
        break;
      else
        Console.WriteLine("\n数组最少1个元素,最多20个元素.\n"); 
    }
    //接受数组元素
    Console.WriteLine("------------------------------------------");
    Console.WriteLine("---------------输入数组元素---------------");
    Console.WriteLine("------------------------------------------");
    for(i=0;i<n;i++)
    {
        Console.Write("<"+(i+1)+">");
        string s1=Console.ReadLine();
        arr[i]=Int32.Parse(s1);
    }
    char ch='y';
    do
    {
      //要搜索的数
      Console.Write("请键入您要查找的数");     
      int item=Convert.ToInt32(Console.ReadLine());
      //应用二叉搜索
      int lowerbound=0;
      int upperbound=n-1;
      //获取中间元素的索引
      int mid=(lowerbound+upperbound)/2;
      int ctr=1;
      while((item!=arr[mid])&&(lowerbound<=upperbound)) //在数组中搜索元素的循环
      {
        if(item>arr[mid])
          lowerbound=mid+1;
        else
          upperbound=mid-1;
        mid=(lowerbound+upperbound)/2;
        //ctr++;
      }
      if(item==arr[mid])
        Console.Write("\n"+item.ToString()+"发现了位置:"+(mid+1).ToString());
      else
        Console.Write("\n"+item.ToString()+"在数组中没有发现");
        Console.Write("\n比较次数:"+ctr);
        Console.Write("\n继续搜索(y/n)");
        ch=char.Parse(Console.ReadLine());
    }while((ch=='y')||(ch=='Y'));
} 
}

/*
编写一个在含有20个数的数中使用线性搜索算法一个给定数的程序,如果要搜索的元素在列表中出现多次,则该程序应该显示第一次出现的位置,还应该显示所作
的比较总数。
*/
using System;
class SequentialSearch
{
  static void Main(string[]args)
  {
    int[]arr=new int[20]; //要搜索的数组
    int n;                //数组中的元素
    int i;  //获取在数组中存储的元素
    while(true)
    {
      Console.Write("请输入数组的元素个数:");
      string s=Console.ReadLine();
      n=Int32.Parse(s);
      if((n>0)&&(n<=20))
        break;
      else
        Console.WriteLine("\n数组最少1个元素,最多20个元素.\n"); 
    }
    //接受数组元素
    Console.WriteLine("------------------------------------------");
    Console.WriteLine("---------------输入数组元素---------------");
    Console.WriteLine("------------------------------------------");
    for(i=0;i<n;i++)
    {
        Console.Write("<"+(i+1)+">");
        string s1=Console.ReadLine();
        arr[i]=Int32.Parse(s1);
    }
    char ch='y';
    int  ctr;
    do
    {
      //接受要搜索的数
      Console.Write("\n请输入您要搜索的数:");
      int item=Convert.ToInt32(Console.ReadLine());
      //应用线性搜索
      ctr=0;
      for(i=0;i<n;i++)
      {
        ctr++;
        if(arr[i]==item)
        {
          Console.WriteLine("\n"+item.ToString()+"发现在位置"+(i+1).ToString());
          break;  
        } 
      }
      if(i==n)
      {
        Console.WriteLine("\n"+item.ToString()+"在数组中没有发现元素");
        Console.WriteLine("\n比较的次数为:"+ctr);
        Console.Write("\n继续搜索(y/n):");
        ch=Char.Parse(Console.ReadLine());  
      }
    }while((ch=='Y')||(ch=='y'));
  } 
}




目录
相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
69 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
13天前
|
算法 搜索推荐 数据库
二分搜索:高效的查找算法
【10月更文挑战第29天】通过对二分搜索的深入研究和应用,我们可以不断挖掘其潜力,为各种复杂问题提供高效的解决方案。相信在未来的科技发展中,二分搜索将继续发挥着重要的作用,为我们的生活和工作带来更多的便利和创新。
20 1
|
1月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
25 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
|
30天前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
32 4
|
1月前
|
搜索推荐 算法
数据结构与算法学习十四:常用排序算法总结和对比
关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
19 0
数据结构与算法学习十四:常用排序算法总结和对比
|
1月前
|
存储 缓存 分布式计算
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
这篇文章是关于数据结构与算法的学习指南,涵盖了数据结构的分类、数据结构与算法的关系、实际编程中遇到的问题以及几个经典的算法面试题。
29 0
数据结构与算法学习一:学习前的准备,数据结构的分类,数据结构与算法的关系,实际编程中遇到的问题,几个经典算法问题
|
1月前
|
机器学习/深度学习 搜索推荐 算法
探索数据结构:初入算法之经典排序算法
探索数据结构:初入算法之经典排序算法
|
1月前
|
算法 Java 索引
数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
19 0
|
1月前
|
机器学习/深度学习 存储 算法
【数据结构与算法基础】——算法复杂度
【数据结构与算法基础】——算法复杂度
|
5月前
|
算法 C++ Python
数据结构与算法===贪心算法
数据结构与算法===贪心算法

热门文章

最新文章