Пример #1
0
        /// <summary>
        /// * 插值查找算法:
        /// * 要求:有序,线性结构
        /// * 时间复杂度O[log(n)]
        /// * middle = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low)
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="des"></param>
        /// <returns></returns>
        static int InsertValue_Search(int[] arr, int key, out SearchRecord recorder)
        {
            recorder = new SearchRecord();

            int search_count = 0;

            int low  = 0;
            int high = arr.Length - 1;

            while (low <= high)
            {
                ++search_count;

                int middle = low + (key - arr[low]) / (arr[high] - arr[low]) * (high - low);

                // recorder.Progress.Add(SearchRecord.FormatProgress(middle, middle));

                //先拿中间的值与查找的值比较,大于中间的值,说明查找的值索引在[low,middle)
                if (key == arr[middle])
                {
                    recorder.Index = middle;
                    recorder.Count = search_count;

                    return(middle);
                }
                else if (key < arr[middle])
                {
                    high = middle - 1;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else
                {
                    low = middle + 1;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
            }

            recorder.Index = -1;
            return(-1);
        }
Пример #2
0
        /// <summary>
        /// * 二分查找算法:
        /// * 要求:有序,线性结构
        /// * 时间复杂度O[log(n)]
        /// * 循环实现
        /// * middle = (low + high) / 2;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="des"></param>
        /// <returns></returns>
        static int Binary_Search(int[] arr, int key, out SearchRecord recorder)
        {
            recorder = new SearchRecord();

            int search_count = 0;

            int low  = 0;
            int high = arr.Length - 1;

            while (low <= high)
            {
                ++search_count;

                int middle = (low + high) / 2;
                //先拿中间的值与查找的值比较,大于中间的值,说明查找的值索引在[low,middle)

                recorder.Progress.Add(SearchRecord.FormatProgress(middle, middle));

                if (key == arr[middle])
                {
                    recorder.Count = search_count;
                    recorder.Index = middle;

                    return(middle);
                }
                else if (key < arr[middle])
                {
                    high = middle - 1;

                    recorder.Progress.Add("*" + SearchRecord.FormatProgress(low, high));
                }
                else
                {
                    low = middle + 1;

                    recorder.Progress.Add("*" + SearchRecord.FormatProgress(low, high));
                }
            }

            recorder.Index = -1;
            return(-1);
        }
Пример #3
0
        /// <summary>
        /// * 斐波那契 查找:
        /// * 要求:有序,线性结构
        /// * 时间复杂度O[log(n)]
        /// * middle = low + Fib[k - 1] - 1;
        ///
        /// 修改部分:
        /// 传入数组之后不创建临时数组, 根据数组长度在斐波那契数组中index值,
        /// 判断 if (mid >= arr.Length) {
        ///     high = mid - 1; fibIndex = fibIndex - 1;
        /// } else {
        ///     // 原来判断方法
        /// }
        /// </summary>
        /// <param name="arr">需要查找的原数组</param>
        /// <param name="key">查找的元素</param>
        /// <param name="recorder"></param>
        /// <param name="fibIndex">数组长度在斐波那契数组中index值, 如果不提供, 会自动计算</param>
        /// <returns></returns>
        static int Fibonacci_Search_Improved(int[] arr, int key, out SearchRecord recorder, int fibIndex = -1)
        {
            recorder = new SearchRecord();

            int search_count = 0;

            int low  = 0;
            int high = arr.Length - 1;
            int mid  = 0;

            //斐波那契分割数值下标
            if (fibIndex < 0)
            {
                int k = 0;

                //获取斐波那契分割数值下标
                while (arr.Length > Fib[k] - 1)
                {
                    k++;
                }

                fibIndex = k;
            }

            while (low <= high)
            {
                ++search_count;

                // low:起始位置
                // 前半部分有f[k-1]个元素,由于下标从0开始
                // 则-1 获取 黄金分割位置元素的下标
                mid = low + Fib[fibIndex - 1] - 1;

                recorder.Progress.Add(SearchRecord.FormatProgress(mid, mid));

                if (mid >= arr.Length)
                {
                    // 如果超出数组长度, 选哟查找的元素肯定在分割点左侧
                    // 这样判断就不需要新建和补齐临时数组了
                    high = mid - 1;

                    fibIndex = fibIndex - 1;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else
                {
                    if (arr[mid] > key)
                    {
                        // 查找前半部分,高位指针移动
                        high = mid - 1;
                        // (全部元素) = (前半部分)+(后半部分)
                        //   f[k]  =  f[k-1] + f[k-1]
                        // 因为前半部分有f[k-1]个元素,所以 k = k-1
                        fibIndex = fibIndex - 1;

                        recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                    }
                    else if (arr[mid] < key)
                    {
                        // 查找后半部分,高位指针移动
                        low = mid + 1;
                        // (全部元素) = (前半部分)+(后半部分)
                        //   f[k]  =  f[k-1] + f[k-1]
                        // 因为后半部分有f[k-2]个元素,所以 k = k-2
                        fibIndex = fibIndex - 2;

                        recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                    }
                    else
                    {
                        recorder.Count = search_count;

                        recorder.Index = mid;
                        return(mid);
                    }
                }
            }

            recorder.Index = -1;
            return(-1);
        }
Пример #4
0
        /// <summary>
        /// * 斐波那契 查找:
        /// * 要求:有序,线性结构
        /// * 时间复杂度O[log(n)]
        /// * middle = low + Fib[k - 1] - 1;
        ///
        /// 修改部分:
        /// 传入数组是按照斐波那契长度-1且补齐的数组
        /// </summary>
        /// <param name="arr">原数组按照斐波那契长度-1且补齐</param>
        /// <param name="key">查找的元素</param>
        /// <param name="recorder"></param>
        /// <param name="fibIndex">数组长度在斐波那契数组中index值, 如果不提供, 会自动计算</param>
        /// <returns></returns>
        static int Fibonacci_Search(int[] temp, int key, out SearchRecord recorder, int fibIndex = -1)
        {
            recorder = new SearchRecord();

            int search_count = 0;

            int low  = 0;
            int high = temp.Length - 1;
            int mid  = 0;

            //斐波那契分割数值下标
            if (fibIndex < 0)
            {
                int k = 0;

                //获取斐波那契分割数值下标
                while (temp.Length > Fib[fibIndex] - 1)
                {
                    fibIndex++;
                }
            }

            while (low <= high)
            {
                ++search_count;

                // low:起始位置
                // 前半部分有f[k-1]个元素,由于下标从0开始
                // 则-1 获取 黄金分割位置元素的下标
                mid = low + Fib[fibIndex - 1] - 1;

                recorder.Progress.Add(SearchRecord.FormatProgress(mid, mid));

                if (temp[mid] > key)
                {
                    // 查找前半部分,高位指针移动
                    high = mid - 1;
                    // (全部元素) = (前半部分)+(后半部分)
                    //   f[k]  =  f[k-1] + f[k-1]
                    // 因为前半部分有f[k-1]个元素,所以 k = k-1
                    fibIndex = fibIndex - 1;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else if (temp[mid] < key)
                {
                    // 查找后半部分,高位指针移动
                    low = mid + 1;
                    // (全部元素) = (前半部分)+(后半部分)
                    //   f[k]  =  f[k-1] + f[k-1]
                    // 因为后半部分有f[k-2]个元素,所以 k = k-2
                    fibIndex = fibIndex - 2;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else
                {
                    recorder.Count = search_count;

                    //如果为真则找到相应的位置
                    if (mid <= high)
                    {
                        recorder.Index = mid;
                        return(mid);
                    }
                    else
                    {
                        //出现这种情况是查找到补充的元素
                        //而补充的元素与high位置的元素一样
                        recorder.Index = high;
                        return(high);
                    }
                }
            }

            recorder.Index = -1;
            return(-1);
        }
Пример #5
0
        /// <summary>
        /// * 斐波那契 查找:
        /// * 要求:有序,线性结构
        /// * 时间复杂度O[log(n)]
        /// * middle = low + Fib[k - 1] - 1;
        ///
        /// 由于创建数组需要消耗大量时间 (new int[500000] 大约耗时24ms, 但查找过程只需0.03秒左右)
        /// 所以后面两个版本不再函数中创建新的数组
        ///
        /// 第二种于第三种方法都可以, 耗时差别不大
        /// </summary>
        /// <param name="arr">需要查找的原数组</param>
        /// <param name="key">查找的元素</param>
        /// <returns></returns>
        static int Fibonacci_Search(int[] arr, int key, out SearchRecord recorder)
        {
            recorder = new SearchRecord();

            int search_count = 0;

            int low  = 0;
            int high = arr.Length - 1;
            int mid  = 0;

            //斐波那契分割数值下标
            int k = 0;

            //获取斐波那契分割数值下标
            while (arr.Length > Fib[k] - 1)
            {
                k++;
            }

            //创建临时数组
            int[] temp = new int[Fib[k] - 1];
            Array.Copy(arr, temp, arr.Length);
            //序列补充至f[k]个元素
            //补充的元素值为最后一个元素的值
            for (int i = arr.Length; i < temp.Length; i++)
            {
                temp[i] = arr[high];
            }

#if !DEBUG
            foreach (var item in temp)
            {
                Console.Write(item + " ");
            }
            Console.WriteLine();
#endif

            while (low <= high)
            {
                ++search_count;

                // low:起始位置
                // 前半部分有f[k-1]个元素,由于下标从0开始
                // 则-1 获取 黄金分割位置元素的下标
                mid = low + Fib[k - 1] - 1;

                recorder.Progress.Add(SearchRecord.FormatProgress(mid, mid));

                if (temp[mid] > key)
                {
                    // 查找前半部分,高位指针移动
                    high = mid - 1;
                    // (全部元素) = (前半部分)+(后半部分)
                    //   f[k]  =  f[k-1] + f[k-1]
                    // 因为前半部分有f[k-1]个元素,所以 k = k-1
                    k = k - 1;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else if (temp[mid] < key)
                {
                    // 查找后半部分,高位指针移动
                    low = mid + 1;
                    // (全部元素) = (前半部分)+(后半部分)
                    //   f[k]  =  f[k-1] + f[k-1]
                    // 因为后半部分有f[k-2]个元素,所以 k = k-2
                    k = k - 2;

                    recorder.Progress.Add(SearchRecord.FormatProgress(low, high));
                }
                else
                {
                    recorder.Count = search_count;

                    //如果为真则找到相应的位置
                    if (mid <= high)
                    {
                        recorder.Index = mid;
                        return(mid);
                    }
                    else
                    {
                        //出现这种情况是查找到补充的元素
                        //而补充的元素与high位置的元素一样
                        recorder.Index = high;
                        return(high);
                    }
                }
            }

            recorder.Index = -1;
            return(-1);
        }