二分查找,插值查找,斐波那契查找:
1.二分查找:
伪代码:
while(left<right)
begin
if key == arr[left] or key == arr[right] or key == arr[left+right/2]
return index
else if key< arr[(left+index)/2]
then right = (left+right)/2
else
left = (left+right)/2
end
示例代码:
public int MidSearch(List<int> arr, int searchValue)
{
if (arr == null || arr.Count == 0)
return -1;
if (arr.Count == 1)
return arr[0] == searchValue ? 0 : -1;
var lowIndex = 0;
var highIndex = arr.Count - 1;
while (lowIndex < highIndex)
{
if (arr[lowIndex] == searchValue) return lowIndex;
if (arr[highIndex] == searchValue) return highIndex;
var midIndex = (lowIndex + highIndex) / 2;
if (arr[midIndex] == searchValue) return midIndex;
if (arr[midIndex] < searchValue)
{
lowIndex = midIndex + 1;
}
else
{
highIndex = midIndex - 1;
}
}
return -1;
}
2.插值查找:
Note:区别在于二分法在计算中值索引时候一直是/2 ,而插值查找的关键在于查找公式。
思路与二分法一样,只是计算索引时把mid = (left+right)/2 替换为:
left + (key - arr[left]) * (right - left) / (arr[right] - arr[left]);
示例代码:
public int InterpolationSearch(List<int> arr, int searchValue)
{
if (arr == null || arr.Count == 0)
return -1;
if (arr.Count == 1)
return arr[0] == searchValue ? 0 : -1;
var lowIndex = 0;
var highIndex = arr.Count - 1;
while (lowIndex < highIndex)
{
if (arr[lowIndex] == searchValue) return lowIndex;
if (arr[highIndex] == searchValue) return highIndex;
var midIndex = lowIndex + (searchValue - arr[lowIndex]) * (highIndex - lowIndex) / (arr[highIndex] - arr[lowIndex]);
if (arr[midIndex] == searchValue) return midIndex;
if (arr[midIndex] < searchValue)
{
lowIndex = midIndex + 1;
}
else
{
highIndex = midIndex - 1;
}
}
return -1;
}
3.斐波那契查找:
1.建立斐波那契数组
2.查找
示例代码:
private void F_InitOnce()
{
if (F == null)
{
F = new List<int>();
//init Fibonacci array
F.Add(1);
F.Add(1);
for (int i = 2; i < 50; i++)
{
F.Add(F[i - 1] + F[i - 2]);
}
}
}
public int FibonacciSearch(List<int> arr, int key)
{
int low, high, mid, k, n;
low = 0;
n = arr.Count;
high = arr.Count;
k = 0;
while (n > F[k] - 1) k++;
while (low <= high)
{
mid = low + F[k - 1] - 1;
if (key < arr[mid])
{
high = mid - 1;
--k;
}
else if (key > arr[mid])
{
low = mid + 1;
k = k - 2;
}
else
{
return n;
}
}
return -1;
}
UT:
[TestMethod]
public void MidSearch()
{
var arr = new List<int>() { 1, 4, 8, 29, 31, 45, 78, 90, 102, 167, 220 };
var searcher = new SearchStudy();
for (var i = 0; i < arr.Count; i++)
{
var ret = searcher.InterpolationSearch(arr, arr[i]);
Assert.AreEqual(ret, i);
}
var toBeSearched = 32;
var ret2 = searcher.MidSearch(arr, toBeSearched);
Assert.AreEqual(ret2, -1);
}
[TestMethod]
public void InterpolationSearch()
{
var arr = new List<int>() { 1, 4, 8, 29, 31, 45, 78, 90, 102, 167, 220 };
var searcher = new SearchStudy();
for (var i = 0; i < arr.Count; i++)
{
var ret = searcher.InterpolationSearch(arr, arr[i]);
Assert.AreEqual(ret, i);
}
var cannotFind = 32;
var ret2 = searcher.InterpolationSearch(arr, cannotFind);
Assert.AreEqual(ret2, -1);
}
[TestMethod]
public void FibonacciSearch()
{
var arr = new List<int>() { 1, 4, 8, 29, 31, 45, 78, 90, 102, 167, 220 };
var searcher = new SearchStudy();
for (var i = 0; i < arr.Count; i++)
{
var ret = searcher.FibonacciSearch(arr, arr[i]);
Assert.AreEqual(ret, i);
}
var cannotFind = 32;
var ret2 = searcher.FibonacciSearch(arr, cannotFind);
Assert.AreEqual(ret2, -1);
}