using System;
using System.Collections.Generic;
using System.Text;
namespace 基本查找算法
{
class Program
{
static void Main(string[] args)
{
}
#region 顺序查找
/// <summary>
/// 顺序查找
/// </summary>
/// <param name="arr"></param>
/// <param name="sValue"></param>
/// <returns></returns>
static bool SeqSearch(int[] arr, int sValue)
{
for (int i = 0; i < arr.Length; i++)
if (arr[i] == sValue)
return true;
return false;
}
/// <summary>
/// 查找最小值
/// </summary>
/// <param name="arr"></param>
/// <returns></returns>
static int FindMin(int[] arr)
{
int min = arr[0];
for (int i = 1; i < arr.Length; i++)
{
if (arr[i] < min)
min = arr[i];
}
return min;
}
#endregion
#region 自组织数据加快顺序查找速度
//因为要查找的数据大概会遵循80-20规则,所以允许数据进行组织是明智的,
//其中80-20规则以为这在数据集合上80%的查找操作都是为了查找到数据集合内20%的数据
//自组织将最终把20%的数据放在数据集的开始部分,这样顺序查找就可以快速的找到他们了
static int[] arr=new int[50];
static bool SeqSearch(int sValue)
{
for (int index = 0; index < arr.Length; index++)
{
if (arr[index] == sValue)
{
swap(index, 0);
return true;
}
}
return false;
}
private static void swap(int item1, int item2)
{
int temp = arr[item1];
arr[item1] = arr[item2];
arr[item2] = temp;
}
#endregion
//用seqsearch方法的问题就是在多次查找过程中会相当多次的把频繁访问的数据项移来移去,
//这里希望把移动到数据集合开始出的数据项保留下来,并且当对集合后部一个后续数据项
// 成功定位的时候也不用把已保存的数据项移动回去
//1,值交换那些招到的且位置远离数据集合开始处的数据项。这样纸需要确定到底在数据集合内多么靠后的元素才需要交换
//再次遵循80-20,这里可以定义一条原则,那就是只有当数据项的位置位于数据集合前
//20%数据项之外的时候才可以把它重新定位到数据集合的开始部分
static int SeqSearch(int sValue)
{
for (int index = 0; index < arr.Length; index++)
{
if (arr[index] == sValue && index > (arr.Length * 0.2))
{
swap(index, 0);
return index;
}
else
if (arr[index] == sValue)
return index;
return -1;
}
//若无法再数据集合中找到数据项,那么就没有理由去检测该项在数据集合内的索引位置
}
//2,就是重写Seqsearch方法,从而使得此方法可以把找到的数据项与数据集合内此项之前的元素进行交换,
//采用这种方法类似于数据排序时所用到的冒泡排序方法,页就是说最终会把最频繁方位到的数据项
//按照他们的方式到达数据集合的前端,同时,这种方法也保证了不会把已经在数据集合前段的数据项移来移去
static int SeqSearch(int sValue)
{
for (int index = 0; index < arr.Length; index++)
{
if (arr[index] == sValue)
{
swap(index, index - 1);
return index;
}
return -1;
}
}
#region 二叉查找算法
//当要查找的记录从头到尾都是有序排列的时候,为找到数值可以执行一种顺序查找更加有效的查找。这种查找被称为是 二叉查找
//为了使用这种算法,首先需要把数据按顺序(最好是升序)存储到数组内(当然,其他数据结构也一样)
//算法的第一步就是设置查找的上限和下限,在查找的开始,上限和下限就是数组的上限和下限
//然后通过吧上限和下限相加后除以2的操作就可以计算出数组的中节点,接着把存储在中间点上的数组元素与要查找的数值进行比较。
//如果两者相同,那么就表示找到了该值,同时查找算法页就结束
//如果要查找的数值小于中间点的值,那么就通过从中间点减去1的操作计算出新的上限,
//否者若是要查找的数值大于中间点的值,那么就把中间点加1求出新的下届。
//此算法反复执行直到上限和下限相等时终止,这也以为着已经对数组全部查找完了
public int binSearch(int value)
{
int upperBound, lowerBound, mid;
upperBound = arr.Length - 1;
lowerBound = 0;
while (lowerBound <= upperBound)
{
mid = (upperBound + lowerBound) / 2;
if (arr[mid] == value)
{
return mid;
}
else
{
if (value < arr[mid])
{
upperBound = mid - 1;
}
else
{
lowerBound = mid + 1;
}
}
}
return -1;
}
#endregion
#region 递归二叉查找算法
//尽管在上面讲述的二叉查找算法是正确的,但他其实不是解决问题的通常方案,
// 二叉查找算法实际上是一种递归算法,因为此算法会不断的划分数组直到找到所要的数据项,
//才会终止,而每次的划分都是表示成一个比原有问题规模更小的同类问题。
// 这种分析问题的方式使得人们终于发现了执行二叉查找的递归算法。
//递归二叉查找算法 要比 迭代的效率慢10倍左右
public int RbinSearch(int value, int lower, int upper)
{
if (lower > upper)
{
return -1;
}
else
{
int mid;
mid = (lower + upper) / 2;
if (value < arr[mid])
return RbinSearch(value, lower, mid - 1);
else if (value == arr[mid])
return mid;
else
return RbinSearch(value,mid+1,upper);
}
}
//最后Array类中拥有的内置的二叉查找方法。此方法有两个参数,数组名和要查找的数据,
//他会返回该数据项在内置的位置,或者是由于没找到而返回-1
public int Bsearch(int value)
{
return Array.BinarySearch(arr, value);
}
//内置的数据结构和算法要比用户自定义的算法执行速度快10倍左右~
//小结:
//查找数据结合内的数值是一种随处可见的计算机操作,
//最简单的查找数据集合的方法是从数据集合的头部开始,
//知道查找到该数据集合的末尾才结束。这种算法适合用于较小且无序的数据集合
// 如果数据集合是有序排列的,那么二叉查找算法会是一种比较好的选择,
//二叉查找会持续划分数据集合知道找到所要查找的数据项位置,
// 大家可以采用迭代的方式或递归方式编写二叉查找算法,c#内置的Array类包含有内置的二叉查找方法,
// 在需要使用二叉查找算法时可以使用此方法
#endregion
}
}