序文
前の 2 つの記事では、一般的な並べ替えアルゴリズムを紹介しましたが、さらに実際にはマスターする必要がある検索アルゴリズムがあります。次に、検索アルゴリズムと古典的な二分探索法の実装方法について説明します。
全文は約 [ 3000]語で、ナンセンスではなく、テクニックを学び原理を理解するための純粋なドライグッズです。この記事には豊富な事例と写真付きのビデオが含まれているため、記事内の技術的な概念をよりよく理解して使用することができ、十分な啓発的な思考を得ることができます。
1. 検索アルゴリズム
1. 一般的に使用される検索アルゴリズムの概要
Java で一般的に使用される検索アルゴリズムは次のとおりです。
二分探索
線形探索法
補間探索法
フィボナッチ探索法
次に、これらの検索アルゴリズムがどのようなものであるかを簡単に説明します。
2.二分探索法
二分探索法は、クエリ効率が非常に高い検索アルゴリズムであり、二分探索法とも呼ばれます。アルゴリズムの核となる考え方は分割統治戦略に基づいています。要素がソートされた後、それらは継続的に半分に検索されます。時間計算量はO (log 2 N)、 空間計算量は O( 1) 。
3. 線形探索法
これは、配列をループするメソッドと同等です。見つかった場合は配列の添字を返し、見つからなかった場合は -1 を返します。順序付き配列と順序なし配列に適しています。
4. 補間探索方法
この方法は二分探索に基づいているため、中間値は適応的です。大量のデータと均等に分散されたキーワードを含むルックアップ テーブル。二分探索法に比べて検索速度は速いですが、キーワードの分布が均一でない場合には二分探索法より優れているとは限りません。
5. フィボナッチ探索法
この方法では、まず黄金分割点を計算する必要があります。つまり、最初に線分を 2 つの部分に分割し、全長に対する一方の部分の比率が、この部分に対するもう一方の部分の比率と等しくなります。最初の 3 桁の値は 0.618 (黄金分割比) です。その原理は二分探索法と似ていますが、黄金分割点に近づくようにmidの値のみが変更されます。つまり、mid = left +F(k-1) -1。
この方法は順序付けされた配列のクエリに適しています。
上記のいくつかの検索アルゴリズムについて、二分探索方法とその実装に焦点を当てて説明します。
2.二分探索法
1 はじめに
二分探索法は、クエリ効率が非常に高い検索アルゴリズムであり、二分探索法とも呼ばれます。アルゴリズムの核となる考え方は分割統治戦略に基づいています。要素がソートされた後、それらは継続的に半分に検索されます。時間計算量はO (log 2 N)、 空間計算量は O( 1) 。
2. 核となるアイデア
このアルゴリズムの核心的な考え方は、実際には分割統治戦略を採用することです。まず、検索される順序が順序どおりである必要があり、次に、検索ごとに検索範囲を半分に減らすという原則に従います。 、つまり、シーケンスの中間の値と検索するキーワードが毎回取得されます。比較して、この 2 つが等しい場合は、検索が成功したことを意味します。中間の値が値より大きければ、検索は成功です。チェックしたいキーワードを入力し、シーケンスの前半で検索プロセスを繰り返します。中央の位置の値がチェック対象のキーワードより小さい場合、この検索プロセスはシーケンスの後半で目的のキーワードが得られるまで繰り返されます。コンテンツが見つかりました。二分探索法の検索プロセスを次の図に示します。
上図の検索プロセスは次のように要約できます。
まず配列をソートします。
配列の中央の要素を計算します。
検索されたキー項目キーと中間要素を比較します。
key = middle 要素の場合は、中間のインデックス位置を直接返します。
キー > 中央の要素の場合、キーが配列の右半分にあることを意味し、配列の後半 (右) で手順 2 ~ 4 を繰り返します。
キー < 中央の要素の場合、キーが配列の左半分にあることを意味するため、左半分で手順 2 ~ 4 を繰り返す必要があります。
知らせ:
シーケンスの並べ替え規則は配列の並べ替え順序に関連しています。つまり、大きいものから小さいものへの並べ替えの結果は、小さいものから大きいものへの並べ替えの結果とは異なります。また、二分探索法は、次の場合には検索に使用できません。秩序が乱れています!
一般に、二分探索のプロセスは二分探索ツリーのプロセスとまったく同じです。ソートされた配列を平衡二分探索ツリーと見なす場合、配列の中点はツリーのルート ノードであり、半分にした後の中点は次のサブツリーのルート ノード、というようになります。各ツリールートノードの目標値と中央値の大小を常に判断することで、次のステップで検索する要素が左の部分木にあるのか、右の部分木にあるのかを判断できます。コードを実装すると、左右に 2 つのポインターを維持でき、ポインターの間の範囲が検索範囲になります。
3. メリットとデメリット
二分探索法は優れた検索アルゴリズムですが、長所と短所もあります。
その利点は、検索中の比較の数が少なく、検索速度が速く、平均パフォーマンスが良いことです。
欠点は、検索時に参照するテーブルが順序付けされたテーブルである必要があり、挿入と削除が難しいことです。
4. 適用可能なシナリオ
二分探索法の利点と欠点に基づいて、その適用可能なシナリオを要約できます。
二分探索法は、頻繁に検索されるが変更が少なく、検索に必要な配列が順序付き配列構造である順序付きリストに適しています。プログラム内のソートされたデータの検索など、特に記憶域がコンパクトで限られている場合に使用します。
5. 実施方法
Java では、次の 3 つの具体的なバイナリ検索実装方法が提供されています。
- 反復法を使用します。
- 再帰を使用します。
- Arrays.binarySearch() メソッドを使用します。
次に、これら 3 つの方法をそれぞれ紹介します。
3. 反復実装
二分探索は反復的に実装され、実装の考え方は次のとおりです。
- まず配列を宣言し、昇順に並べ替えます。
- 次に、検索するキーを定義します。
- 次に、配列の中央値を計算し、キーを中央値と比較します。
- 最後に、キーが中央値より小さいか大きいかに従って、キーはそれぞれ配列の左半分または右半分で検索されます。
次に、反復的に実装されたコードをリストします。
1. コードの実装
二分検索を反復的に実装するコードは次のとおりです。
public class IteratorSearch {
public static void main(String[] args) {
//待查找数组
int[] nums = {
15, 2, 9, 3, 18, 1, 66, 20};
//先对数组进行升序排列
Arrays.sort(nums);
System.out.println("数组排序结果:" + Arrays.toString(nums));
//查找关键字
int searchKey = 18;
System.out.println("要查找的关键字= " + searchKey);
//左侧边界索引
int low = 0;
//右侧边界索引
int high = nums.length - 1;
// 计算中间值索引
int mid = (low + high) / 2;
//循环的进行迭代计算
while (low <= high) {
//如果数组的中间值小于查找关键字,则去数组的右侧进行折半查找
if (nums[mid] < searchKey) {
//将左侧边界的索引置为mid+1
low = mid + 1;
} else if (nums[mid] == searchKey) {
//如果数组的中间值等于要查找的关键字,则表示直接就找到了要查找的内容
System.out.println("要查的内容位于索引[ " + mid +" ]处");
break;
} else {
//如果数组的中间值大于查找关键字,则去数组的左侧进行折半查找
//此时将右侧边界的索引值置为mid-1
high = mid - 1;
}
//不断修改mid值
mid = (low + high) / 2;
}
if (low > high) {
System.out.println("数组中没有要查找的内容!");
}
}
}
2. 実行結果
上記コードの実行結果は以下のようになり、クエリキーワードが無事に見つかったことがわかります。
4. 再帰的実装
二分探索法の再帰的実装は、反復法に比べて比較的簡単です。
1. コードの実装
二分探索を再帰的に実装するコードは次のとおりです。
public class RecurrenceSearch {
public static int binarySearch(int[] nums, int low, int high, int searchKey) {
if (high >= low) {
// 计算中间索引
int mid = low + (high - low) / 2;
// 如果中间值等于要查找的关键字,直接返回中间值的索引
if (nums[mid] == searchKey) {
return mid;
}
//如果数组的中间值大于查找关键字,则去数组的左侧进行折半查找
// 此时将右侧边界的索引值置为mid-1
if (nums[mid] > searchKey) {
//进行递归调用,修改high的值
return binarySearch(nums, low, mid - 1, searchKey);
} else {
//如果数组的中间值小于查找关键字,则去数组的右侧进行折半查找,进行递归查找,修改low的值
return binarySearch(nums, mid + 1, high, searchKey);
}
}
return -1;
}
public static void main(String[] args) {
//待查找数组
int[] nums = {
15, 2, 9, 3, 18, 1, 66, 20};
//先对数组进行升序排列
Arrays.sort(nums);
System.out.println("数组排序结果:" + Arrays.toString(nums));
//查找关键字
int searchKey = 3;
System.out.println("要查找的关键字= " + searchKey);
int high = nums.length - 1;
int result = binarySearch(nums, 0, high, searchKey);
if (result == -1){
System.out.println("数组中没有要查找的key!");
} else{
System.out.println("要查的内容位于索引[ " + result +" ]处");
}
}
}
2. 実行結果
上記コードの実行結果は以下のようになり、クエリキーワードが無事に見つかったことがわかります。
5. Arrays.binarySearch() メソッドの実装
Java の Arrays クラス自体は、binarySearch()
指定された配列に対してバイナリ検索を直接実行できるメソッドを提供します。このメソッドは、配列と検索するキーをパラメーターとして受け取り、配列内のキーの位置を返します。キーが見つからない場合は -1 を返します。
1. コードの実装
Arrays.binarySearch()
のコード実装は次のとおりです。このメソッドの実装は非常に簡単であることがわかります。
public class BinarySearcher {
public static void main(String[] args) {
//待查找数组
int[] nums = {
15, 2, 9, 3, 18, 1, 66, 20};
//先对数组进行升序排列
Arrays.sort(nums);
System.out.println("数组排序结果:" + Arrays.toString(nums));
//查找关键字
int searchKey = 3;
System.out.println("要查找的关键字= " + searchKey);
//直接调用Arrays.binarySearch的二分查找法
int result = Arrays.binarySearch(nums, searchKey);
if (result == -1) {
System.out.println("数组中没有要查找的key!");
} else {
System.out.println("要查的内容位于索引[ " + result + " ]处");
}
}
}
2. 実行結果
上記コードの実行結果は以下のようになり、クエリキーワードが無事に見つかったことがわかります。
6. 結論
ここまで、一般的な検索アルゴリズムをいくつか紹介してきましたが、もう学習しましたか?
二分探索法は、二分探索法とも呼ばれます。アルゴリズムの中心的な考え方は、分割統治戦略に基づいています。要素がソートされた後、二分探索は継続的に実行されます。時間計算量は O(log2N)、空間計算量は O(1) で、アルゴリズムの 3 つの実装方法、反復法、再帰法、Arrays.binarySearch() メソッドを知る必要もあります。