有序表查找,首先我们的数据是要有序的,不可以任意摆放,也就是说,在所需要的数据体中,各项数据都是有某种规律来进行排列,总之,有序对于查找肯定是有好处的。
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近的区域),查找效果是要弱于折半查找的