说明
(此系列帖子记录数据结构学习成果,如侵犯视频作者权益,立删)
作者账号 哔哩哔哩:离忧夏天
顺序查找
顺序查找,即线性查找,从列表的头部开始,依次逐个对列表中的元素进行比较,直到到达列表尾部。
//顺序查找法
//时间复杂度O(n)
public static int OrderSearch(int[] arr, int target)
{
for (int i = 0; i < arr.Length; i++)
if (target == arr[i])
return i;
return -1;
}
二分查找
要求:查找的列表有序
二分查找,也称折半查找,j将查找元素与列表中间位置的元素进行比较,根据比较结果判断待查找的元素可能在列表的左半部分还是右半部分,然后继续对相应的半部分进行二分查找,直到找到匹配的元素或确定元素不存在于列表中。
l :列表最左侧位置
r:列表最右侧位置
mid:列表中间位置
通过依次将目标target与mid索引的元素进行比较
①target > mid,证明在mid右侧,这时将l = mid +1,并重新计算mid
②target < mid,证明在mid左侧,这时将r = mid - 1,并重新计算mid
直到target = mid,或者r < l,证明元素不存在与表中
//二分查找法 => 只能用于有序数组
//时间复杂度O(log n)
public static int BinarySearch(int[] arr, int target)
{
int l = 0;
int r = arr.Length - 1;
while (l <= r)
{
//为了避免整数溢出(l+r可能非常大,超过整数的范围)
int mid = l + (r - l) / 2;
if (target < arr[mid])
{
r = mid - 1;
}
else if (target > arr[mid])
{
l = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
}
时间复杂度
时间复杂度 | |
---|---|
顺序查找 | O(n) |
二分查找 | log₂(n) |
编写一个用于测试读取文件的方法,用于测试性能比较
class Test1
{
//读取名为filename的文件并将数据存储到数组中返回
internal static int[] ReadFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open);
StreamReader sr = new StreamReader(fs);
List<int> list = new List<int>();
while (!sr.EndOfStream)
{
int num = int.Parse(sr.ReadLine() ?? string.Empty);
list.Add(num);
}
fs.Close();
sr.Close();
return list.ToArray();
}
}
在主函数中进行测试
static void Main(string[] args)
{
string filename1 = "测试文件2/游戏会员表.txt";
string filename2 = "测试文件2/游戏用户表.txt";
int[] arr1 = Test1.ReadFile(filename2);
int[] arr2 = Test1.ReadFile(filename2);
Console.WriteLine("游戏会员数量: " + arr1.Length);
Console.WriteLine("调查用户数量: " + arr2.Length);
Console.WriteLine();
Stopwatch t1 = new Stopwatch();
Stopwatch t2 = new Stopwatch();
Console.WriteLine("顺序查找法");
t1.Start();
int sum1 = 0;//记录普通客户数量
for (int i = 0; i < arr2.Length; i++)
{
int target = arr2[i];
if (Test1.OrderSearch(arr1, target) == -1)
{
Console.WriteLine(target);
sum1++;
}
}
t1.Stop();
Console.WriteLine("查找到:" + sum1 + "个零氪玩家");
Console.WriteLine("运行时间:" + t1.ElapsedMilliseconds + "ms");
Console.WriteLine();
//二分查找法
t2.Start();
Array.Sort(arr1);
int sum2 = 0;
for (int i = 0; i < arr2.Length; i++)
{
int target = arr2[i];
if (Test1.BinarySearch(arr1, target) == -1)
{
Console.WriteLine(target);
sum2++;
}
}
t2.Stop();
Console.WriteLine("查找到:" + sum2 + "个零氪玩家");
Console.WriteLine("运行时间:" + t2.ElapsedMilliseconds + "ms");
}
我们可以清楚的看到,对于100W级别的列表查询,顺序查找法是相当耗时的,而对于二分查找法,非常高效。