首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

.NET 陣列搜尋演算法全解析:Exists、Find、FindAll、BinarySearch 效能比較

     編輯:關於.NET

前言

搜尋是最基礎的資料操作。.NET Array 類別提供豐富的靜態搜尋方法,配合委派、匿名方法、Lambda 演進,程式碼愈發簡潔。本文詳細解析各方法用法與效能特性。

1. Array.Exists - 判斷是否存在


int[] numbers = { 3, 7, 2, 4, 10, 1 };

// 傳統委派寫法
static bool MatchInt(int input) => input == 2;
bool exists = Array.Exists(numbers, new Predicate(MatchInt));
bool exists2 = Array.Exists(numbers, MatchInt);  // 方法群組簡寫

// 匿名方法 (C# 2.0)
bool exists3 = Array.Exists(numbers, delegate(int i) { return i == 2; });

// Lambda (C# 3.0+) - 最簡潔
bool exists4 = Array.Exists(numbers, i => i == 2);

IL 碼顯示:匿名方法與 Lambda 編譯結果相同,皆透過委派實作。Lambda 只是語法糖,但更直觀。

2. Array.Find / FindLast - 取得第一個/最後一個符合項目


int first = Array.Find(numbers, i => i == 2);        // 回傳 2
int last = Array.FindLast(numbers, i => i % 2 == 0); // 回傳最後一個偶數
  • 找到即停止 (Find) 或從尾端反向搜尋 (FindLast)
  • 找不到回傳預設值 (int 為 0),無法區分「找到 0」與「找不到」,參考類型則回傳 null

3. Array.FindAll - 取得所有符合項目


int[] evens = Array.FindAll(numbers, i => i % 2 == 0); // { 2, 4, 10 }

// 配合 Array.ForEach 列印
Array.ForEach(evens, i => Console.WriteLine(i));

// 一行寫法
Array.ForEach(Array.FindAll(numbers, i => i % 2 == 0), i => Console.WriteLine(i));

4. Array.FindIndex / FindLastIndex - 取得索引位置


int idx = Array.FindIndex(numbers, i => i == 1);       // 5
int lastIdx = Array.FindLastIndex(numbers, i => i == 1); // 5 (只有一個 1)

5. Array.BinarySearch - 二分搜尋 (需排序)

原理

折半搜尋:陣列必須已排序。每次比較中間元素,縮小一半搜尋範圍。時間複雜度 O(log n) vs 線性 O(n)。

未排序陣列呼叫後果

  • 不會拋出例外
  • 回傳負數或錯誤索引
  • 務必先呼叫 Array.Sort

效能實測:1000 萬筆資料搜尋 100


int[] numbers = new int[10_000_000];
Random rnd = new Random();
for (int i = 0; i < numbers.Length; i++) numbers[i] = rnd.Next(10_000_000);

// 線性搜尋
Stopwatch sw = Stopwatch.StartNew();
int found = Array.Find(numbers, i => i == 100);
sw.Stop();
Console.WriteLine($"線性搜尋: {sw.ElapsedMilliseconds} ms");

// 二分搜尋 (含排序時間)
sw.Reset(); sw.Start();
Array.Sort(numbers);  // 排序耗時
sw.Stop();
Console.WriteLine($"排序時間: {sw.ElapsedMilliseconds} ms");

sw.Reset(); sw.Start();
int idx = Array.BinarySearch(numbers, 100);
sw.Stop();
Console.WriteLine($"二分搜尋: {sw.ElapsedMilliseconds} ms");

典型結果分析

操作耗時說明
線性搜尋~50-200 ms視目標位置而定,最差掃描全陣列
排序~1500-2500 msO(n log n),一次性成本
二分搜尋< 1 ms極快,但需已排序

決策指南

  • 單次搜尋、小資料量、無序資料:Find/Exists (線性)
  • 多次搜尋、大資料量、可接受排序成本:Sort + BinarySearch
  • 頻繁搜尋、資料動態變更:改用 SortedList、Dictionary、HashSet (O(1) 查找)

進階:自訂比較器


// BinarySearch 使用自訂比較
int idx = Array.BinarySearch(numbers, 100, Comparer.Create((a, b) => b - a)); // 降序陣列

// FindAll 多條件
var results = Array.FindAll(numbers, i => i > 50 && i < 100 && i % 2 == 0);

總結

.NET 陣列搜尋方法配合 Lambda 表達式,語法極度簡潔。核心選擇在於線性 vs 二分:資料是否排序、搜尋頻率、資料量大小決定策略。理解各方法回傳值語意 (特別是找不到時的預設值),避免邏輯錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved