数据结构学习-有序表查找

        有序表查找,首先我们的数据是要有序的,不可以任意摆放,也就是说,在所需要的数据体中,各项数据都是有某种规律来进行排列,总之,有序对于查找肯定是有好处的。

1.折半查找

        /// <summary>
        /// 以查找0以上的整数为例子进行计算,如果返回-1则代表没有此关键字。
        /// </summary>
        /// <param name="a">对应的数据组</param>
        /// <param name="key">查找的关键字</param>
        /// <returns></returns>
        public static int Binary_SearchOne(int[] a,int key)
        {
            int output = -1;
            int midData;//中间数组标签
            int lowData = 0;//最低数组标签
            int hightData = a.Length-1;
            while(lowData <= hightData)
            {
                midData = (lowData + hightData) / 2;
                if (a[midData] < key)
                {
                    lowData = midData + 1;
                }
                else if (a[midData] > key)
                {
                    hightData = midData - 1;
                }
                else
                {
                    output = midData;
                    break;
                }
            }
            return output;
        }

此算法比较好理解,主要是对数据中间值进行判断,如果关键值小,就取小的一边进行操作,关键值大,则相反。

2.差值查找

        /// <summary>
        /// 插值查找,对比上述的折半,主要是在midData中进行了替换计算方式。
        /// </summary>
        /// <param name="a">对应的数据组</param>
        /// <param name="key">查找的关键字</param>
        /// <returns></returns>
        public static int Binary_SearchTwo(int[] a, int key)
        {
            int output = -1;
            int midData;
            int lowData = 0;
            int hightData = a.Length - 1;
            while (lowData <= hightData)
            {
                midData = lowData + ( hightData - lowData ) * (key - a[lowData]) / (a[hightData] - a[lowData]);
                if (a[midData] < key)
                {
                    lowData = midData + 1;
                }
                else if (a[midData] > key)
                {
                    hightData = midData - 1;
                }
                else
                {
                    output = midData;
                    break;
                }
            }
            return output;
        }

      此方法与折半方法的区别在于查找的关键字key与查找表中最大最小记录的关键字比较后的查找方式,核心就在于插值的计算公式:

                                    (key - a[lowData])/(a[high]-a[low])

另外,此方法适合表长较大,而关键字分布有比较均匀的查找表,但是如果是极端不均匀的数据,如{0,2,3,2000,2000001,2000000001}这种类型数据,插值法并不是合适的选择。

3.斐波那契查找

    对于这个查找方式,我们先要了解一下关于斐波那契数列的数组,数列从第三项开始(包含第三项),每一项都等于前两项之和{1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...}以此进行类推形成对应的斐波那契数列,那么斐波那契数组在此查找方法中起到什么作用了,个人总结就是定点作用,利用黄金分割原理来对midData进行定点。

    //斐波那契数组

    int[] dataFibonacciData = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
                                                 377,610, 987,1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368 };

     //斐波那契查找方法

    int Fibonacci_Search(int[] a,int key)
        {
            int lowData = 0;
            int highData = a.Length - 1;
            int n = a.Length - 1;
            int midData;
            int i;
            int k = 0;
            int output = -1;
            while (n  > dataFibonacciData[k] - 1)
            {
                k++;
            }            
            for ( i = n; i< dataFibonacciData[k] - 1; i++)
            {
                a[i] = a[n];//补全数组,后面补齐的数组取值都为初始数组的最大值。
            }
            while ( lowData <= highData )
            {
                midData = lowData + dataFibonacciData[k - 1] - 1;
                if (key < a[midData])
                {
                    highData = midData - 1;
                    k = k - 1;
                }
                else if (key > a[midData])
                {
                    lowData = midData + 1;
                    k = k - 2;
                }
                else
                {
                    if (midData < n)
                        output = midData;
                    else
                        output = n;
                }
            }
            return output;
        }

    其实斐波那契查找,主要是运用了黄金分割的方式进行查找,如果查询的数据一直在长半区(也就是黄金分割离0近的区域),查找效果是要弱于折半查找的

转载于:https://my.oschina.net/u/3712269/blog/1837974

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值