検索は最も単純なアルゴリズムです。ただし、検索アルゴリズムは異なり、ギャップも異なります。
1.センチネルで順番に検索します。
とても簡単です。コードを始めましょう。
int[] a = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static int findKey(int[] a, int key) {
int index = a.length;
while(index -- > 0) {
if(a[index] == key)
return index;
}
return -1;
}
これを行うには、2つの判断(1つはwhileループ、もう1つはifステートメント)を行うことです。番兵がいる場合は、1つの判断を保存できます。通常、センチネルは配列の0の位置に配置されます。
配列の構造と検索機能が次のように変更されました。
int key = 5;
int[] a = new int[] { key, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static int findKey(int[] a, int key) {
int index = a.length - 1;
while (a[index --] == key) {
return index;
}
return 0;
}
この場合、findKeyの結果が0を返す場合は、検索が失敗したこと、つまり、配列aにキー値の位置がないことを意味します。
2.二分探索
二分探索は、配列の順序、つまり、大きいものから小さいものへ、または小さいものから大きいものへと基づいています。次に、配列の内容は1 2 3 4 5 6 7 8 9であり、key = 8の位置が検出されます。アルゴリズムの実装を見ることができます。
public static int findKey(int[] a, int key) {
int low = 0;
int high = a.length - 1;
int middle;
while (low <= high) {
middle = (low + high) / 2;
if (a[middle] == key)
return middle;
else if (key < a[middle])
high = middle - 1;
else
low = middle + 1;
}
return -1;
}
つまり、8を見つけたい場合は、低= 0、高= 8、中間=(8 + 0)/ 2 = 4です。[中央] <キーなので、4〜8をロックして、もう一度半分に折ります。
また、最初に二分探索アルゴリズムは配列の順序に基づいていると言いましたが、このようにすると検索効率が高くなります。一般的に言えば、半分と再帰に関しては、効率はO(log2N)です。
3.ブロック検索
ブロック検索は、順次検索とバイナリ検索の混合に似ています。
検索された配列はキー順に並べられ、各ノードには最大のキーフィールドとブロックの最初のノードへのポインターが含まれます。
構造は次のとおりです。
class Indetype {
int max; // 块间最大值
int start; // 块的起始位置
}
まず、ブロック間の最大値を見つける必要があります。
各グループのサイズは任意です。より良いデモンストレーションのために、各グループのサイズを7に設定しました。また、現在のブロックの最小値が前のブロックの最大値よりも大きくなるようにするには、
最初にインデックステーブルを作成します。
class IndexType {
int max; // 块内最大值
int start; // 块内开始位置
}
public static int findKey(int[] a, int key) {
int pieceCount = 0; // 计算块个数
if (a.length % 7 == 0)
pieceCount = a.length / 7;
else
pieceCount = a.length / 7 + 1;
IndexType[] indexType = new IndexType[pieceCount]; // 初始化块数据
for (int i = 0; i < pieceCount; i++) {
indexType[i] = new IndexType();
indexType[i].start = 7 * i;
}
for (int i = 0; i < pieceCount - 1; i++) { // 找到前pieceCount - 1块的最大值
int max = indexType[i].start;
for (int j = indexType[i].start; j < indexType[i + 1].start; j++) {
if (max < a[j])
max = a[j];
}
indexType[i].max = max;
}
int max = indexType[pieceCount - 1].start; // 找到最后一块的最大值
for (int i = indexType[pieceCount - 1].start; i < a.length; i++) {
if (max < a[i])
max = a[i];
}
indexType[pieceCount - 1].max = max;
if(key > indexType[pieceCount-1].max) // 如果大于最后一块的最大值,就返回-1
return -1;
// 找到key所在的块内范围,采用顺序查找
int index = 0;
for (index = 0; index < pieceCount - 1; index++) {
if (indexType[index].max >= key)
break;
}
//找到块内具体的位置,采用顺序查找
int low = 0;
int high = 0;
if (index == pieceCount-1) {
low = indexType[index].start;
high = a.length;
}
else {
low = indexType[index].start;
high = indexType[index +1].start;
}
for(int i = low; i < high; i ++) {
if(a[i] == key)
return i;
}
return -1;
}
上記の関数を呼び出します。
int a[] = new int[] { 22, 12, 13, 8, 9, 20, 33,
42, 44, 39, 24, 48, 60, 58,
74, 57, 86, 53, 91, 95, 97,
100, 98, 101
};
int key = 20;
int position = findKey(a, key);
System.out.println(position);