• 基本的查找你知道几个?


    关于查找

    查找又称检索,是从大量的数据中找出所需的数据,也可以简单地说是确定一个已给定的数据是否出现在某个数据表中。表通常是指文件,而文件是记录的集合,每个记录都是由若干个数据项组成的,其间一个或一组能唯一识别该记录的数据项称为该记录的关键字(keyword)。查找包括很多种:顺序查找、折半查找、分块查找以及哈希查找法。

    顺序查找

    核心思想:把序列中的元素进行遍历,找到符合条件的结果就结束

    比较次数:最快1次,最慢n次

    何时使用:

    • 针对于无序序列,如果要实现查找序列中的所有满足条件的元素,那么比较次数一定是n次,因为找到其中一个,并不一定意味着找到所有的,因而要把所有的元素都遍历一遍才行。
    • 如果是有序序列,要查找序列中所有满足条件的元素,比较次数要少一些,只需从开始满足的地方,到第一个不满足的地方就可以结束了,不必要等到序列末尾。
     1         int Find(int[] ary, int target)
     2         {
     3             for (int i = 0; i < ary.Length; i++)
     4             {
     5                 if (ary[i] == target)
     6                 {
     7                     //找到了就返回找到的位置
     8                     return i;
     9                 }
    10             }
    11             //没找到就返回-1,表示没找到
    12             return -1;
    13         }
    View Code

    折半查找

    核心思想:先确定待查找记录所在的的区间,然后逐步缩小查找范围,直到找到或找不到记录为止

    时间复杂度:折半查找算法的效率是O(logn)

    何时使用:

    • 当表的长度n很大时,该方法很能显示出其时间效率
    • 适合表中元素很少发生改动
     1 int binary(int v[],int n,int cha)
     2 {
     3     int low,high,mid;
     4     low=0;
     5     high=n-1;
     6 
     7     while(low<=high)
     8     {
     9        mid=(low+high)/2; //折半
    10        if(cha<v[mid])
    11        {
    12             high=mid-1;    //前半部分查找
    13        }
    14        else if(cha>v[mid])
    15        {
    16             low=mid+1;     //后半部分查找
    17        }
    18        else
    19             return mid;
    20     }
    21     return 0;    //没找到
    22 }            
    View Code

    PS:折半查找查找的表还是线性表

    分块查找

    核心思想:分块查找是顺序查找和折半查找的结合体

    时间复杂度:介于顺序与折半

    何时使用:

    • 要求表中元素是逐段有序的,块与块之间可以无序
     1         int SeqSearch(SeqList<int> R, int Key)
     2         {
     3             int i;
     4             R.Data[R.GetLength()] = Key;
     5             for (i = 0; R.Data[i] != Key; i++) ;
     6             if (i > R.Maxsize - 2)
     7                 return -2;
     8             else
     9                 return i;
    10         }
    View Code

    哈希法(散列法)

    简介一下:哈希法不同于前面三种查找方法(这三种都是通过对关键字进行一系列的比较,逐步缩小范围,知道确定节点的存储位置或确定查找失败),哈希法不经过任何比较,一次存取就能得到所查元素,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系,使得每个关键字和结构中一个唯一的存储位置相对应,这样查找时只需对节点进行某种运算就能确定节点在表中的位置

    核心思想:找到哈希函数(比较次数与所含节点的个数无关)

      1 Search
      2 
      3 using System;
      4 using System.Collections.Generic;
      5 using System.Linq;
      6 using System.Text;
      7 
      8 namespace DataStructure
      9 {
     10     public interface IListDS<T>
     11     {
     12         int GetLength();             //求长度
     13         void Clear();                //清空操作
     14         bool IsEmpty();              //判断线性表是否为空
     15         bool IsFull();               //判断数据表是否已满
     16         void Append(T item);         //附加操作
     17         void Insert(T item, int i);  //插入操作
     18         T Delete(int i);             //删除操作
     19         T GetElement(int i);         //取表元
     20         int Locate(T value);         //按值查找
     21         void Reserve();              //倒置 
     22     }
     23 
     24     public class SeqList<T> : IListDS<T>
     25     {
     26         private int maxsize;        //顺序表的容量
     27         private T[] data;           //数组,用于存储数据表中的数据元素
     28         private int last;           //指示数据表中最后一个元素的位置
     29 
     30         //索引器
     31         public T this[int index]
     32         {
     33             get { return data[index]; }
     34             set { data[index] = value; }
     35         }
     36 
     37         public T[] Data
     38         {
     39             get { return data; }
     40             set { data = value; }
     41         }
     42 
     43         //属性 最后一个元素的位置
     44         public int Last
     45         {
     46             get { return last; }
     47         }
     48 
     49         //属性 容量
     50         public int Maxsize
     51         {
     52             get { return maxsize; }
     53             set { maxsize = value; }
     54         }
     55 
     56         //构造函数
     57         public SeqList(int size)
     58         {
     59             data = new T[size];
     60             maxsize = size;
     61             last = -1;
     62         }
     63 
     64         public int GetLength()
     65         {
     66             return last + 1;
     67         }
     68 
     69         public void Clear()
     70         {
     71             last = -1;
     72         }
     73 
     74         public bool IsEmpty()
     75         {
     76             if (last == -1)
     77                 return true;
     78             else
     79                 return false;
     80         }
     81 
     82         public bool IsFull()
     83         {
     84             if (last == maxsize - 1)
     85                 return true;
     86             else
     87                 return false;
     88         }
     89 
     90         public void Append(T item)
     91         {
     92             if (IsFull())
     93             {
     94                 Console.WriteLine("List is full !");
     95                 return;
     96             }
     97             data[++last] = item;
     98         }
     99 
    100         public void Insert(T item, int i)
    101         {
    102             if (IsFull())
    103             {
    104                 Console.WriteLine("List is Full !");
    105                 return;
    106             }
    107             if (i < 1 || i > last + 2)
    108             {
    109                 Console.WriteLine("Postion is Error !");
    110                 return;
    111             }
    112             if (i == last + 2)
    113             {
    114                 data[i - 1] = item;
    115             }
    116             else
    117             {
    118                 for (int j = last; j >= i - 1; j--)
    119                 {
    120                     data[j + 1] = data[j];
    121                 }
    122                 data[i - 1] = item;
    123             }
    124             ++last;
    125         }
    126 
    127         public T Delete(int i)
    128         {
    129             T tem = default(T);
    130             if (IsEmpty())
    131             {
    132                 Console.WriteLine("List is Empty !");
    133                 return tem;
    134             }
    135             if (i < 1 || i > last + 1)
    136             {
    137                 Console.WriteLine("Postion is Error !");
    138                 return tem;
    139             }
    140             if (i == last + 1)
    141             {
    142                 tem = data[last--];
    143                 return tem;
    144             }
    145             else
    146             {
    147                 tem = data[i - 1];
    148                 for (int j = i; j <= last; j++)
    149                 {
    150                     data[j] = data[j + 1];
    151                 }
    152             }
    153             --last;
    154             return tem;
    155         }
    156 
    157         public T GetElement(int i)
    158         {
    159             if (IsEmpty() || i < 1 || i > last + 1)
    160             {
    161                 Console.WriteLine("List is Empty or Postion is Error !");
    162                 return default(T);
    163             }
    164             return data[i - 1];
    165         }
    166 
    167         public int Locate(T value)
    168         {
    169             if (IsEmpty())
    170             {
    171                 Console.WriteLine("List is Empty !");
    172                 return -1;
    173             }
    174             int i = 0;
    175             for (i = 0; i <= last; i++)
    176             {
    177                 if (value.Equals(data[i]))
    178                     break;
    179             }
    180             if (i > last)
    181             {
    182                 return -1;
    183             }
    184             return i;
    185         }
    186 
    187         public void Reserve()
    188         {
    189             T tem;
    190             int len = GetLength();
    191             for (int i = 0; i <= len / 2; i++)
    192             {
    193                 tem = data[i];
    194                 data[i] = data[len - 1];
    195                 data[len - 1] = tem;
    196             }
    197         }
    198 
    199         /// <summary>
    200         /// 将两个升序整型顺序表合并成一个升序顺序表
    201         /// 思路:依次扫描La Lb中的元素,比较La和Lb中当前元素,将较小的元素值赋值给Lc,如此直到一个被扫描完,然后把未完的那个剩余的元素付给Lc
    202         /// </summary>
    203         /// <param name="La"></param>
    204         /// <param name="Lb"></param>
    205         /// <returns></returns>
    206         public SeqList<int> Merge(SeqList<int> La, SeqList<int> Lb)
    207         {
    208             SeqList<int> Lc = new SeqList<int>(La.Maxsize + Lb.Maxsize);
    209             int i = 0;
    210             int j = 0;
    211 
    212             while ((i <= La.GetLength() - 1) && (j <= Lb.GetLength() - 1))
    213             {
    214                 if (La[i] < Lb[j])
    215                 {
    216                     Lc.Append(La[i++]);
    217                 }
    218                 else
    219                 {
    220                     Lc.Append(Lb[j++]);
    221                 }
    222             }
    223             //如果La中还有元素
    224             while (i <= La.GetLength() - 1)
    225             {
    226                 Lc.Append(La[i++]);
    227             }
    228             //如果Lb中还有元素
    229             while (i < Lb.GetLength() - 1)
    230             {
    231                 Lc.Append(Lb[i++]);
    232             }
    233 
    234             return Lc;
    235         }
    236 
    237         /// <summary>
    238         /// 已知顺序表La 构造顺序表Lb 使其包含La中所有不相同的数据元素 
    239         /// 思路: 先把La中的第一个元素付给Lb 然后从La的第二个元素开始 每一个元素与Lb的每一个元素比较 不同则附加到Lb末尾 
    240         /// </summary>
    241         /// <param name="La"></param>
    242         /// <returns></returns>
    243         public SeqList<int> Purge(SeqList<int> La)
    244         {
    245             SeqList<int> Lb = new SeqList<int>(La.Maxsize);
    246             Lb.Append(La[0]);
    247             for (int i = 1; i <= La.GetLength() - 1; ++i)
    248             {
    249                 int j = 0;
    250                 for (j = 0; j <= Lb.GetLength() - 1; ++j)
    251                 {
    252                     if (La[i].CompareTo(Lb[j]) == 0)
    253                     {
    254                         break;
    255                     }
    256                 }
    257                 //没有相同的元素,把La中的元素附加到Lb
    258                 if (j > Lb.GetLength() - 1)
    259                 {
    260                     Lb.Append(La[i]);
    261                 }
    262             }
    263             return Lb;
    264         }
    265 
    266 
    267        
    268 
    269     }
    270 
    271     /// <summary>
    272     /// 定义解决冲突的链表的结点类型
    273     /// </summary>
    274     public class chaintype
    275     {
    276         private int key;
    277         private chaintype next;
    278 
    279         public int Key
    280         {
    281             get { return key; }
    282             set { key = value; }
    283         }
    284 
    285         public chaintype Next
    286         {
    287             get { return next; }
    288             set { next = value; }
    289         }
    290     }
    291 
    292 
    293     public class SearchArithMetic
    294     {
    295 
    296         /// <summary>
    297         /// 插入排序
    298         /// </summary>
    299         /// <param name="R"></param>
    300         public void InsertSort(SeqList<int> R)
    301         {
    302             for (int i = 1; i < R.Maxsize; i++)
    303             {
    304                 if (R.Data[i] < R.Data[i - 1])
    305                 {
    306                     int temp = R.Data[i];
    307                     int j = 0;
    308                     for (j = i - 1; j >= 0 && temp < R.Data[j]; j--)
    309                     {
    310                         R.Data[j + 1] = R.Data[j];
    311                     }
    312                     R.Data[j + 1] = temp;
    313                 }
    314             }
    315         }
    316        
    317         /// <summary>
    318         /// 顺序查找算法
    319         /// </summary>
    320         /// <param name="R"></param>
    321         /// <param name="Key"></param>
    322         /// <returns></returns>
    323         public int SeqSearch(SeqList<int> R, int Key)
    324         {
    325             int i;
    326             R.Data[R.GetLength()] = Key;
    327             for (i = 0; R.Data[i] != Key; i++) ;
    328             if (i > R.Maxsize - 2)
    329                 return -2;
    330             else
    331                 return i;
    332         }
    333 
    334         /// <summary>
    335         /// 二分查找算法
    336         /// </summary>
    337         /// <param name="R"></param>
    338         /// <param name="Key"></param>
    339         /// <returns></returns>
    340         public int BinSearch(SeqList<int> R, int Key)
    341         {
    342             int low = 0, high = R.GetLength() - 1, mid;  //设置当前查找区间的上下界的初值
    343             while (low <= high)
    344             {
    345                 mid = (low + high) / 2;
    346                 if (R.Data[mid] == Key) return mid;
    347                 if (R.Data[mid] > Key)
    348                     high = mid - 1;
    349                 else
    350                     low = mid + 1;
    351             }
    352             return -1;
    353         }
    354 
    355         /// <summary>
    356         /// 除模取余法的哈希函数
    357         /// </summary>
    358         /// <param name="key"></param>
    359         /// <param name="Mod"></param>
    360         /// <returns></returns>
    361         public int Hash(int key, int Mod)
    362         {
    363             return key % Mod;
    364         }
    365 
    366         /// <summary>
    367         /// 在哈希表中插入记录,用链表法解决冲突
    368         /// </summary>
    369         /// <param name="a"></param>
    370         /// <param name="key"></param>
    371         /// <param name="Mod"></param>
    372         /// <returns></returns>
    373         public bool HashInsert(chaintype[] a, int key, int Mod)
    374         {
    375             int i;
    376             i = Hash(key, Mod);
    377             chaintype pre;
    378             chaintype cur;
    379             pre = a[i];
    380             cur = a[i];
    381 
    382             while (cur != null && cur.Key != key)
    383             {
    384                 pre = cur;
    385                 cur = cur.Next;
    386             }
    387 
    388             /*未查找到时插入该记录在对应的链表尾*/
    389             if (cur == null)
    390             {
    391                 cur = new chaintype();
    392                 cur.Key = key;
    393                 cur.Next = null;
    394                 /*在该链插入第一个记录*/
    395                 if (a[i] == null)
    396                     a[i] = cur;
    397                 else
    398                     pre.Next = cur;
    399                 return true;
    400             }
    401             return false;
    402         }
    403 
    404 
    405         public chaintype HashSearch(chaintype[] a, int key, int Mod)
    406         {
    407             chaintype p;
    408             int i = Hash(key, Mod);
    409             p = a[i];
    410             while (p != null && p.Key != key)
    411             { p = p.Next; }
    412             if (p == null) return null;
    413             else
    414                 return p;
    415         }
    416     }
    417     class Search
    418     {
    419         /*
    420         /// <summary>
    421         /// 顺序查找
    422         /// </summary>
    423         /// <param name="R"></param>
    424         /// <param name="Key"></param>
    425         /// <returns></returns>
    426         public static int SeqSearch(SeqList<int> R, int Key)
    427         {
    428             int i;
    429             R.Data[R.GetLength()] = Key;
    430             for (i = 0; R.Data[i] != Key; i++) ;
    431             if (i > R.Maxsize - 2)
    432                 return -2;
    433             else
    434                 return i;
    435         }
    436 
    437         /// <summary>
    438         /// 二分查找
    439         /// </summary>
    440         /// <param name="R"></param>
    441         /// <param name="Key"></param>
    442         /// <returns></returns>
    443         public static int BinSearch(SeqList<int> R, int Key)
    444         {
    445             int low = 0, high = R.GetLength() - 1, mid;  //设置当前查找区间的上下界的初值
    446             while (low <= high)
    447             {
    448                 mid = (low + high) / 2;
    449                 if (R.Data[mid] == Key) return mid;
    450                 if (R.Data[mid] > Key)
    451                     high = mid - 1;
    452                 else
    453                     low = mid + 1;
    454             }
    455             return -2;
    456         }
    457 
    458 
    459         static void Main()
    460         {
    461             SeqList<int> queue = new SeqList<int>(10);
    462             queue.Append(10);
    463             queue.Append(20);
    464             queue.Append(30);
    465             queue.Append(40);
    466             queue.Append(50);
    467             queue.Append(60);
    468             queue.Append(70);
    469             queue.Append(80);
    470             queue.Append(90);
    471 
    472             //int location = SeqSearch(queue, 90);
    473             int location = BinSearch(queue, 90);
    474             Console.WriteLine("您查找的数据为表中第{0}位!", location + 1);
    475             Console.ReadKey();
    476 
    477         }
    478         */
    479 
    480         public static void Main()
    481         {
    482             SeqList<int> numList = null;
    483 
    484             numList = new SeqList<int>(12);
    485             chaintype[] a = new chaintype[13];
    486 
    487             char selectFlag;
    488             while (true)
    489             {
    490                 Console.WriteLine("请输入操作选项:");
    491                 Console.WriteLine("1.创建顺序表");
    492                 Console.WriteLine("2.对顺序表执行顺序查找");
    493                 Console.WriteLine("3.对顺序表执行二分查找");
    494                 Console.WriteLine("4.创建哈希表");
    495                 Console.WriteLine("5.在哈希表中查找关键字");
    496                 Console.WriteLine("6.退出");
    497                 selectFlag = Convert.ToChar(Console.ReadLine());
    498                 SearchArithMetic searchA = new SearchArithMetic();
    499                 switch (selectFlag)
    500                 {
    501                     case '1':
    502                         {
    503                             numList.Insert(70, numList.GetLength() + 1);
    504                             numList.Insert(30, numList.GetLength() + 1);
    505                             numList.Insert(40, numList.GetLength() + 1);
    506                             numList.Insert(10, numList.GetLength() + 1);
    507                             numList.Insert(80, numList.GetLength() + 1);
    508                             numList.Insert(20, numList.GetLength() + 1);
    509                             numList.Insert(90, numList.GetLength() + 1);
    510                             numList.Insert(100, numList.GetLength() + 1);
    511                             numList.Insert(75, numList.GetLength() + 1);
    512                             numList.Insert(60, numList.GetLength() + 1);
    513                             numList.Insert(45, numList.GetLength() + 1);
    514 
    515                             Console.WriteLine("已插入顺序表的数字是:");
    516                             Console.WriteLine("70 30 40 10 80 20 90 100 75 60 45");
    517                             break;
    518                         }
    519                     case '2':
    520                         {
    521                             Console.WriteLine("请输入要查找的数字:");
    522                             long time1 = System.DateTime.Now.Ticks;
    523                             int num = Convert.ToInt32(Console.ReadLine());
    524                             int i = searchA.SeqSearch(numList, num);
    525                             if (i == -1)
    526                                 Console.WriteLine("{0}在数字列表中不存在", num);
    527                             else
    528                                 Console.WriteLine("{0}在数字列表中的序号为{1}", num, i);
    529                             long time2 = System.DateTime.Now.Ticks;
    530                             Console.WriteLine("顺序查找用时{0}", time2 - time1);
    531                             break;
    532                         }
    533                     case '3':
    534                         {
    535                             long time1 = System.DateTime.Now.Ticks;
    536                             new SearchArithMetic().InsertSort(numList);
    537                             long time2 = System.DateTime.Now.Ticks;
    538                             Console.WriteLine("请输入要查找的数字:");
    539                             int num = Convert.ToInt32(Console.ReadLine());
    540                             long time3 = System.DateTime.Now.Ticks;
    541                             int i = searchA.BinSearch(numList, num);
    542                             if (i == -1)
    543                                 Console.WriteLine("{0}在数据列表中不存在", num);
    544                             else
    545                                 Console.WriteLine("{0}在数字列表中的序号为{1}", num, i + 1);
    546                             long time4 = System.DateTime.Now.Ticks;
    547                             Console.WriteLine("排序用时{0}", time2 - time1);
    548                             Console.WriteLine("二分查找用时{0}", time4 - time3);
    549                             Console.WriteLine("查找总用时{0}", time4 - time1);
    550                             break;
    551                         }
    552                     case '4':
    553                         {
    554                             searchA.HashInsert(a, 70, 13);
    555                             searchA.HashInsert(a, 30, 13);
    556                             searchA.HashInsert(a, 40, 13);
    557                             searchA.HashInsert(a, 10, 13);
    558                             searchA.HashInsert(a, 80, 13);
    559                             searchA.HashInsert(a, 20, 13);
    560                             searchA.HashInsert(a, 90, 13);
    561                             searchA.HashInsert(a, 100, 13);
    562                             searchA.HashInsert(a, 75, 13);
    563                             searchA.HashInsert(a, 60, 13);
    564                             searchA.HashInsert(a, 45, 13);
    565                             break;
    566                         }
    567                     case '5':
    568                         {
    569                             Console.WriteLine("请输入要查找的数字:");
    570                             long time1 = System.DateTime.Now.Ticks;
    571                             int num = Convert.ToInt32(Console.ReadLine());
    572                             chaintype p = searchA.HashSearch(a, num, 13);
    573                             if(p==null)
    574                                 Console.WriteLine("{0}在数据列表中不存在", num);
    575                             else
    576                                 Console.WriteLine("您查找的关键字是:{0}",p.Key );
    577                             long time2 = System.DateTime.Now.Ticks;
    578                             Console.WriteLine("哈希表查找用时{0}", time2 - time1);
    579                             break;
    580                         }
    581                     case '6':
    582                         {
    583                             return;
    584                         }
    585 
    586 
    587                 }
    588                 Console.WriteLine("按任意键继续");
    589                 Console.ReadLine();
    590             }
    591         }
    592         
    593     }
    594 }
    View Code

    结语

    适当的情景使用适当的算法,慢慢在实际中摸索,IT小菜鸟成长ing

  • 相关阅读:
    python 函数2
    数据结构----栈
    python 函数
    数据结构----队列
    python 数据类型_字典和集合
    python 数据类型_数组和元组
    python 数据类型_整数_浮点数
    数据结构----链表
    laravel5.5 自带的忘记密码邮箱找回功能小记
    laravel5.5使用sendCloud邮件服务
  • 原文地址:https://www.cnblogs.com/vchenpeng/p/3175712.html
Copyright © 2020-2023  润新知