1. Gambaran keseluruhan
Dalam artikel ini, kita akan membahas kelebihan carian binari berbanding carian linier sederhana dan melalui pelaksanaannya di Java.
2. Keperluan untuk Pencarian yang cekap
Katakan kita berada dalam perniagaan menjual wain dan berjuta-juta pembeli mengunjungi aplikasi kita setiap hari.
Melalui aplikasi kami, pelanggan dapat menyaring item yang mempunyai harga di bawah n dolar, memilih sebotol dari hasil carian, dan menambahkannya ke keranjangnya. Kami mempunyai berjuta-juta pengguna yang mencari wain dengan had harga setiap saat. Hasilnya mesti cepat.
Pada bahagian belakang, algoritma kami menjalankan carian linear melalui keseluruhan senarai wain yang membandingkan had harga yang dimasukkan oleh pelanggan dengan harga setiap botol wain dalam senarai.
Kemudian, ia mengembalikan barang yang mempunyai harga kurang dari atau sama dengan had harga. Pencarian linear ini mempunyai kerumitan masa O (n) .
Ini bermakna semakin banyak bilangan botol wain dalam sistem kami, semakin banyak masa yang diperlukan. Masa carian meningkat secara berkadaran dengan jumlah item baru yang diperkenalkan.
Sekiranya kita mula menyimpan item mengikut urutan dan mencari item menggunakan carian binari, kita dapat mencapai kerumitan O (log n) .
Dengan carian binari, masa yang diambil oleh hasil carian secara semula jadi meningkat dengan ukuran set data, tetapi tidak berkadar.
3. Pencarian Binari
Ringkasnya, algoritma membandingkan nilai kunci dengan elemen tengah array; jika mereka tidak sama, separuh di mana kunci tidak boleh menjadi sebahagiannya dihapuskan, dan pencarian berterusan untuk separuh lagi sehingga berjaya.
Ingat - aspek utama di sini adalah bahawa array sudah disusun.
Sekiranya carian berakhir dengan baki separuh kosong, kunci tidak ada dalam larik.
3.1. Implasi berulang
public int runBinarySearchIteratively( int[] sortedArray, int key, int low, int high) { int index = Integer.MAX_VALUE; while (low <= high) { int mid = (low + high) / 2; if (sortedArray[mid] key) { high = mid - 1; } else if (sortedArray[mid] == key) { index = mid; break; } } return index; }
The runBinarySearchIteratively kaedah mengambil sortedArray , kunci & yang rendah & tinggi indeks daripada sortedArray sebagai argumen. Apabila kaedah dijalankan untuk pertama kalinya rendah , indeks pertama Array diurutkan, adalah 0, sementara tinggi , indeks terakhir Array diurutkan, sama dengan panjangnya - 1.
Yang pertengahan adalah indeks tengah-tengah sortedArray . Sekarang algoritma menjalankan gelung sementara membandingkan kunci dengan nilai tatasusunan indeks tengah Array yang disusun .
3.2. Impl berulang
Sekarang, mari kita lihat pelaksanaan yang sederhana dan rekursif juga:
public int runBinarySearchRecursively( int[] sortedArray, int key, int low, int high) { int middle = (low + high) / 2; if (high < low) { return -1; } if (key == sortedArray[middle]) { return middle; } else if (key < sortedArray[middle]) { return runBinarySearchRecursively( sortedArray, key, low, middle - 1); } else { return runBinarySearchRecursively( sortedArray, key, middle + 1, high); } }
The runBinarySearchRecursively kaedah menerima suatu sortedArray , utama, yang rendah dan tinggi indeks daripada sortedArray .
3.3. Menggunakan Susun atur. carian binari ()
int index = Arrays.binarySearch(sortedArray, key);
Array yang diurutkan dan kunci int , yang hendak dicari dalam array bilangan bulat, diteruskan sebagai argumen kepada kaedah binarySearch dari kelas Java Arrays .
3.4. Menggunakan Koleksi. carian binari ()
int index = Collections.binarySearch(sortedList, key);
A sortedList & yang Integer utama , iaitu untuk diperiksa dalam senarai Integer objek, diluluskan sebagai argumen kepada binarySearch kaedah Java Collections kelas.
3.5. Persembahan
Sama ada menggunakan pendekatan rekursif atau berulang untuk menulis algoritma kebanyakannya menjadi pilihan peribadi. Tetapi masih ada beberapa perkara yang harus kita perhatikan:
1. Kekambuhan boleh menjadi lebih perlahan kerana overhead mengekalkan timbunan dan biasanya memerlukan lebih banyak memori
2. Rekursi tidak mesra susun . Ini boleh menyebabkan StackOverflowException ketika memproses set data besar
3. Rekursi menambahkan kejelasan pada kod kerana menjadikannya lebih pendek jika dibandingkan dengan pendekatan berulang
Sebaik-baiknya, carian binari akan melakukan sedikit perbandingan berbanding dengan carian linear untuk nilai n yang besar. Untuk nilai n yang lebih kecil, carian linear dapat menunjukkan prestasi yang lebih baik daripada carian binari.
Kita harus tahu bahawa analisis ini bersifat teori dan mungkin berbeza bergantung pada konteksnya.
Juga, algoritma carian binari memerlukan set data yang diasingkan yang harganya juga . Sekiranya kita menggunakan algoritma penggabungan jenis untuk menyusun data, kerumitan tambahan n log n akan ditambahkan pada kod kita.
Oleh itu, pertama kita perlu menganalisis keperluan kita dengan baik dan kemudian mengambil keputusan mengenai algoritma carian mana yang paling sesuai dengan keperluan kita.
4. Kesimpulan
Tutorial ini menunjukkan pelaksanaan algoritma carian binari dan senario di mana lebih baik menggunakannya daripada carian linear.
Sila cari kod untuk tutorial di GitHub.