1.顺序查找:从数据集合的一端开始逐个查找比较,直到找到目标值或遍历完数据集合。适用于数量较小或无序的情况。
using System;
namespace SearchAlgorithm
{
internal class Program
{
static int SequentialSearch(int[] arr,int key)
{
for(int i=0; i < arr.Length; i++)
{
if(arr[i] == key)
{
return i;
}
}
return -1;
}
static void Main(string[] args)
{
int[] arr = {4,3,-2,8,1};
Console.WriteLine(arr[SequentialSearch(arr, 8)]);
}
}
}
2.二分查找:基于数据有序(升序或降序)的情况查找。从数据集合中间的元素开始查找比较,返回中间元素的索引。如果目标值小于中间值,以中间值的左端(升序)或右端(降序)为新的数据集合;如果目标值大于中间值,则相反;选出的新的数据集合又从中间值查找比较,如此往复。
using System;
namespace SearchAlgorithm
{
internal class Program
{
static int BinarySearch(int[] arr,int key)
{
int left = 0;
int right = arr.Length-1;
while (left <= right)
{
int mid = (left + right) / 2;//计算中间值的索引
if(arr[mid] == key)
{
return mid;
}
else if (arr[mid]<key)
{
left = mid+1;
}
else
{
right = mid-1;
}
}
return -1;
}
static void Main(string[] args)
{
int[] arr = {1,3,5,8,10,13};//有序的前提
Console.WriteLine(arr[BinarySearch(arr, 8)]);
}
}
}
3.差值查找:是对二分查找的优化,以按照差值比例去查找。当数据集合中的元素分布比较均匀时,差值查找的效率比较高;如果数据中的元素分布不均匀,比如出现大量重复或者分布不连续,则查找效率会比较低
using System;
namespace SearchAlgorithm
{
internal class Program
{
static int InterpolationSearch(int[] arr,int key)
{
int low = 0;
int high = arr.Length-1;
while (low <= high)
{
int pos = low + (key - arr[low]) / (arr[high] - arr[low])*(high-low);
if(arr[pos] == key)
{
return pos;
}
else if (arr[pos]<key)
{
low = pos+1;
}
else
{
high = pos-1;
}
}
return -1;
}
static void Main(string[] args)
{
int[] arr = {1,3,5,8,10,13};//有序的前提
Console.WriteLine(InterpolationSearch(arr, 8)]);
}
}
}
4.斐波那契查找
using System;
namespace SearchAlgorithm
{
internal class Program
{
static int[] Fibonacci(int n)
{
int[] f = new int[n + 1];
f[0] = 0;
f[1] = 1;
for (int i = 2; i <= n; i++)
{
f[i] = f[i - 1] + f[i - 2];
}
return f;
}
static int FibonacciSearch(int[] arr, int key)
{
int n = arr.Length;
int[] f = Fibonacci(n);//获取斐波那契数列
int k = 0;//表示斐波那契分割数值的下标
//获取斐波那契分割数值的下标
while (n > f[k] - 1)
{
k++;
}
int[] temp = new int[f[k] - 1];
//因为f[k]-1的值可能大于arr的长度,所以将arr的值复制到新的数组中
Array.Copy(arr, temp, n);
//填充适用arr数组最后的数填充temp,使它保持有序
for (int i = n; i < f[k] - 1; i++)
{
temp[i] = arr[n - 1];
}
int left = 0;
int right = n - 1;
//适用while来找key
while (left <= right)
{
int mid = left + f[k - 1] - 1;
if (key < temp[mid])
{
right = mid - 1;//继续向左边的元素查找
k--;//f[k-1]=f[k-2](左边)+f[k-3](右边);
}
else if (key > temp[mid])
{
left = mid + 1;//继续向右边的元素查找
k -= 2;
}
else
{
if (mid < n)
{
return mid;
}
else
{
return n - 1;
}
}
}
return -1;
}
static void Main(string[] args)
{
int[] arr = { 1, 3, 5, 8, 10, 13 };//有序的前提
Console.WriteLine(arr[FibonacciSearch(arr, 13)]);
}
}
}
084-尚硅谷-图解Java数据结构和算法-斐波那契查找代码实现.avi_哔哩哔哩_bilibili
5.树表查找
using System;
namespace SearchAlgorithm
{
internal class Program
{
static TreeNode insert(TreeNode root, int data)//以递归的形式插入数据
{
if (root == null)
return new TreeNode(data);
if (data < root.data)
root.left = insert(root.left, data);
else if (data > root.data)
root.right = insert(root.right, data);
return root;
}
static bool TreeTableSearch(TreeNode root, int key)//递归查找
{
if (root == null)
return false;
if (root.data == key)
return true;
if (root.data > key)
return TreeTableSearch(root.left, key);
return TreeTableSearch(root.right, key);
}
static void Main(string[] args)
{
int[] arr = {1,3,5,8,10,13};
TreeNode root = null;
for(int i=0;i<arr.Length;i++)
{
root = insert(root, arr[i]);//向树中插入数据
}
if(TreeTableSearch(root,10))
{
Console.WriteLine("找到了");
}
}
}
class TreeNode
{
public int data;
public TreeNode left, right;
public TreeNode(int data)
{
this.data = data;
left = right = null;
}
}
}
6.分块查找
using System;
using System.Collections.Generic;
namespace SearchAlgorithm
{
internal class Program
{
static int blockSearch(int[] arr, int key, int blockSize)//基于块内无序,且块与块之间有序
{
int n = arr.Length;
int blockCount = (int)Math.Ceiling((double)n / blockSize);//表示数组分块后的块的数量
List<int[]> blocks = new List<int[]>();
//将数组中的元素放入块数组中,再将块数组放入blocks链表中
for (int i = 0; i < blockCount; i++)
{
int[] block = new int[blockSize];
for (int j = 0; j < blockSize; j++)
{
int index = i * blockSize + j;
if (index < n)
block[j] = arr[index];
else
break;
}
blocks.Add(block);
}
int blockIndex = -1;//记录key所在的块数组的索引
//找到key所在的块数组
for (int i = 0; i < blockCount; i++)
{
if (key <= blocks[i][blockSize - 1])
{
blockIndex = i;
break;
}
}
if (blockIndex == -1)
return -1;
int[] blockArr = blocks[blockIndex];//key所在的块数组
//找到key再arr中的索引
for (int i = 0; i < blockSize; i++)
{
if (blockArr[i] == key)
return blockIndex * blockSize + i;
}
return -1;
}
static void Main(string[] args)
{
int[] arr = {1,3,5,8,10,13};
int blockSize = 3;
Console.WriteLine(arr[blockSearch(arr, 10, blockSize)]);
}
}
}
7.哈希查找
using System;
using System.Collections.Generic;
namespace SearchAlgorithm
{
internal class Program
{
static int HashValue(int x)//计算哈希值
{
return x % 10;
}
static void HashSearch(int[] arr,int key)
{
Dictionary<int, int> dict = new Dictionary<int, int>();//存储哈希值对应的数组元素
//计算对应的数组元素的哈希值,并将哈希值和数组元素存储字典
for (int i = 0; i < arr.Length; i++)
{
int index = HashValue(arr[i]);
if (!dict.ContainsKey(index))
dict.Add(index, arr[i]);
else // 如果该位置已经有元素,则使用开放地址法解决冲突
{
while (dict.ContainsKey(index))
index = (index + 1) % 10;
dict.Add(index, arr[i]);
}
}
int hash = HashValue(key); // 计算要查找的数组元素的哈希值
if (dict.ContainsKey(hash))
{
if (dict[hash]==key)
{
Console.WriteLine("找到了");
}
}
}
static void Main(string[] args)
{
int[] arr = {1,3,5,8,10,13};
HashSearch(arr, 10);
}
}
}
结语:合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。