zoukankan      html  css  js  c++  java
  • 查找

    查找的算法主要有几种:二分查找,插入查找,斐波那契查找。注:所有的查找算法都是在有序数组中

    二分查找:顾名思义,先从中间值开始查找,然后不断逼近,类似高中的二分法

    二分查找完整代码如下:

    public static int BinarySearch(int[] arr, int left, int right, int value)
            {
                if (left == right)
                {
                    return -1;
                }
                int mid = (left + right) / 2;
                int midVal = arr[mid];
                if (value > midVal)
                {
                    return BinarySearch(arr, mid + 1, right, value);
                }
                else if (value < midVal)
                {
                    return BinarySearch(arr, left, mid - 1, value);
                }
                else
                {
                    return mid;
                }
            }

    二分查找还有个改进算法,可以找到重复的元素,代码如下:

    public static List<int> BinarySearch2(int[] arr, int left, int right, int value)
            {
                if (left == right)
                {
                    return new List<int>();
                }
                int mid = (left + right) / 2;
                int midVal = arr[mid];
                if (value > midVal)
                {
                    return BinarySearch2(arr, mid + 1, right, value);
                }
                else if (value < midVal)
                {
                    return BinarySearch2(arr, left, mid - 1, value);
                }
                else
                {
                    List<int> list = new List<int>();
                    list.Add(mid);
                    int temp = mid - 1;
                    while (true)
                    {
                        //因为二分查找为有序数组 所以在arr[temp]!=value时之间跳出循环
                        if (temp < 0 || arr[temp] != value)
                        {
                            break;
                        }
                        list.Add(temp);
                        temp -= 1;
                    }
                    temp = mid + 1;
                    while (true)
                    {
                        if (temp > arr.Length - 1 || arr[temp] != value)
                        {
                            break;
                        }
                        list.Add(temp);
                        temp += 1;
                    }
                    return list;
                }
            }

    插入查找也可以认为是二分查找的改进,其改进之处在于插入查找插入点不再是中点,而是随着查找值改变(自适应查找)

    插入查找适用于均匀分布的数组,原因很简单 其本质是等比例缩放法 value/mid=arr[右]-arr[左]/arr.Length

    插入查找完整代码如下:

     1 public static int InsertSearch(int[] arr, int left, int right, int value)
     2         {
     3             if (left > right || value < arr[0] || value > arr[arr.Length - 1])
     4             {
     5                 return -1;
     6             }
     7             int mid = left + (right - left) * (value - arr[left]) / (arr[right] - arr[left]);
     8             int midVal = arr[mid];
     9             if (value > midVal)
    10             {
    11                 return InsertSearch(arr, mid + 1, right, value);
    12             }
    13             else if (value < midVal)
    14             {
    15                 return InsertSearch(arr, left, mid - 1, value);
    16             }
    17             else
    18             {
    19                 return mid;
    20             }
    21         }

    斐波那契查找本质也和二分查找类似,其插入点是接近黄金分割点(虽然不知道有什么意义,但人家这么搞跟着搞就对了^^)

    完整代码如下:

     1  //构建斐波那契数列
     2         public static int[] fib()
     3         {
     4             int[] f = new int[20];
     5             f[0] = 1;
     6             f[1] = 1;
     7             for (int i = 2; i < f.Length; i++)
     8             {
     9                 f[i] = f[i - 1] + f[i - 2];
    10             }
    11             return f;
    12         }
    13 
    14         public static int fibSearch(int[] a, int key)
    15         {
    16             int low = 0;
    17             int high = a.Length - 1;
    18             int k = 0;//表示斐波那契分割数值的下标
    19             int mid = 0;//存放mid值
    20             int[] f = fib();
    21             //获取到斐波那契分割数值的下标
    22             while (high > f[k] - 1)
    23             {
    24                 k++;
    25             }
    26             //因为k值可能大于a长度 构建一个数组temp 将a的值全部放入temp 不足用0补
    27             int[] temp = new int[f[k]];
    28             a.CopyTo(temp, 0);
    29             //实际中用a最后的元素填充temp的0部分
    30             for (int i = high + 1; i < temp.Length; i++)
    31             {
    32                 temp[i] = a[high];
    33             }
    34             //用while循环处理 
    35             while (low <= high)
    36             {
    37                 mid = low + f[k - 1] - 1;
    38                 //如果要找到的值在左边
    39                 if (key < temp[mid])
    40                 {
    41                     high = mid - 1;
    42                     //f[k]=f[k-1]+f[k-2] 左边数组为f[k-1] 该数组斐波那契为f[k-1]=f[k-2]+f[k-3]
    43                     k--;
    44                 }
    45                 else if (key > temp[mid])//要找的值在右边
    46                 {
    47                     low = mid + 1;
    48                     k -= 2;
    49                 }
    50                 else //要找的值就是mid 因为是在temp中找的 可能长度大于a.length 所以返回小一点的
    51                 {
    52                     if (mid <= high)//没有超出a
    53                     {
    54                         return mid;
    55                     }
    56                     else//超出了a
    57                     {
    58                         return high;
    59                     }
    60                 }
    61             }
    62             //找不到 返回-1
    63             return -1;
    64         }
     
  • 相关阅读:
    HDU1029 Ignatius and the Princess IV
    UVA11039 Building designing【排序】
    UVA11039 Building designing【排序】
    POJ3278 HDU2717 Catch That Cow
    POJ3278 HDU2717 Catch That Cow
    POJ1338 Ugly Numbers(解法二)
    POJ1338 Ugly Numbers(解法二)
    UVA532 Dungeon Master
    UVA532 Dungeon Master
    POJ1915 Knight Moves
  • 原文地址:https://www.cnblogs.com/TheLin/p/13893575.html
Copyright © 2011-2022 走看看