Αυτό το σεμινάριο θα εξηγήσει τη δυαδική αναζήτηση και την αναδρομική δυαδική αναζήτηση σε Java μαζί με τον αλγόριθμο, την υλοποίηση και τα παραδείγματα κώδικα δυαδικής αναζήτησης σε Java:
Η δυαδική αναζήτηση στη Java είναι μια τεχνική που χρησιμοποιείται για την αναζήτηση μιας στοχευμένης τιμής ή ενός κλειδιού σε μια συλλογή. Είναι μια τεχνική που χρησιμοποιεί την τεχνική "διαίρει και βασίλευε" για την αναζήτηση ενός κλειδιού.
Η συλλογή στην οποία θα εφαρμοστεί η δυαδική αναζήτηση για την αναζήτηση ενός κλειδιού πρέπει να ταξινομηθεί σε αύξουσα σειρά.
Συνήθως, οι περισσότερες από τις γλώσσες προγραμματισμού υποστηρίζουν τις τεχνικές Γραμμική αναζήτηση, Δυαδική αναζήτηση και Κατακερματισμός που χρησιμοποιούνται για την αναζήτηση δεδομένων στη συλλογή. Θα μάθουμε τον κατακερματισμό στα επόμενα σεμινάρια.
Δυαδική αναζήτηση σε Java
Η γραμμική αναζήτηση είναι μια βασική τεχνική. Σε αυτή την τεχνική, ο πίνακας διατρέχεται διαδοχικά και κάθε στοιχείο συγκρίνεται με το κλειδί μέχρι να βρεθεί το κλειδί ή να φτάσει στο τέλος του πίνακα.
Η γραμμική αναζήτηση χρησιμοποιείται σπάνια σε πρακτικές εφαρμογές. Η δυαδική αναζήτηση είναι η πιο συχνά χρησιμοποιούμενη τεχνική, καθώς είναι πολύ ταχύτερη από τη γραμμική αναζήτηση.
Η Java παρέχει τρεις τρόπους για την εκτέλεση δυαδικής αναζήτησης:
- Χρήση της επαναληπτικής προσέγγισης
- Χρήση αναδρομικής προσέγγισης
- Χρήση της μεθόδου Arrays.binarySearch ().
Σε αυτό το σεμινάριο, θα υλοποιήσουμε και θα συζητήσουμε και τις 3 αυτές μεθόδους.
Αλγόριθμος για δυαδική αναζήτηση σε Java
Στη μέθοδο δυαδικής αναζήτησης, η συλλογή διαιρείται επανειλημμένα στη μέση και το στοιχείο κλειδί αναζητείται στο αριστερό ή στο δεξί μισό της συλλογής, ανάλογα με το αν το κλειδί είναι μικρότερο ή μεγαλύτερο από το μεσαίο στοιχείο της συλλογής.
Ένας απλός αλγόριθμος δυαδικής αναζήτησης έχει ως εξής:
- Υπολογίστε το μεσαίο στοιχείο της συλλογής.
- Συγκρίνετε τα βασικά στοιχεία με το μεσαίο στοιχείο.
- Εάν key = μεσαίο στοιχείο, τότε επιστρέφουμε τη μεσαία θέση δείκτη για το κλειδί που βρέθηκε.
- Διαφορετικά Εάν key> mid element, τότε το κλειδί βρίσκεται στο δεξί μισό της συλλογής. Επαναλάβετε έτσι τα βήματα 1 έως 3 στο κάτω (δεξί) μισό της συλλογής.
- Αλλιώς key <μεσαίο στοιχείο, τότε το κλειδί βρίσκεται στο ανώτερο μισό της συλλογής. Ως εκ τούτου, πρέπει να επαναλάβετε τη δυαδική αναζήτηση στο ανώτερο μισό.
Όπως μπορείτε να δείτε από τα παραπάνω βήματα, στη δυαδική αναζήτηση, τα μισά στοιχεία της συλλογής αγνοούνται αμέσως μετά την πρώτη σύγκριση.
Σημειώστε ότι η ίδια ακολουθία βημάτων ισχύει τόσο για την επαναληπτική όσο και για την αναδρομική δυαδική αναζήτηση.
Ας παρουσιάσουμε τον αλγόριθμο δυαδικής αναζήτησης χρησιμοποιώντας ένα παράδειγμα.
Για παράδειγμα , πάρτε τον ακόλουθο ταξινομημένο πίνακα 10 στοιχείων.
Ας υπολογίσουμε τη μεσαία θέση του πίνακα.
Mid = 0+9/2 = 4
#1) Κλειδί = 21
Πρώτον, θα συγκρίνουμε την τιμή του κλειδιού με το στοιχείο [mid] και θα διαπιστώσουμε ότι η τιμή του στοιχείου στο mid = 21.
Έτσι, διαπιστώνουμε ότι key = [mid]. Επομένως, το κλειδί βρίσκεται στη θέση 4 του πίνακα.
#2) Κλειδί = 25
Πρώτα συγκρίνουμε την τιμή του κλειδιού με το μέσο. Καθώς (21 <25), θα αναζητήσουμε άμεσα το κλειδί στο άνω μισό του πίνακα.
Τώρα πάλι θα βρούμε το μέσο για το πάνω μισό της συστοιχίας.
Mid = 4+9/2 = 6
Η τιμή στη θέση [mid] = 25
Τώρα συγκρίνουμε το στοιχείο κλειδί με το μεσαίο στοιχείο. Έτσι (25 == 25), επομένως έχουμε βρει το κλειδί στη θέση [mid] = 6.
Έτσι, διαιρούμε επανειλημμένα τον πίνακα και συγκρίνοντας το στοιχείο κλειδί με το μέσο, αποφασίζουμε σε ποιο μισό θα αναζητήσουμε το κλειδί. Η δυαδική αναζήτηση είναι πιο αποδοτική από άποψη χρόνου και ορθότητας και είναι επίσης πολύ πιο γρήγορη.
Εφαρμογή δυαδικής αναζήτησης Java
Χρησιμοποιώντας τον παραπάνω αλγόριθμο, ας υλοποιήσουμε ένα πρόγραμμα δυαδικής αναζήτησης σε Java χρησιμοποιώντας την επαναληπτική προσέγγιση. Σε αυτό το πρόγραμμα, παίρνουμε έναν πίνακα παραδείγματος και εκτελούμε δυαδική αναζήτηση σε αυτόν τον πίνακα.
import java.util.*; class Main{ public static void main(String args[]){ int numArray[] = {5,10,15,20,25,30,35}; System.out.println("Ο πίνακας εισόδου: " + Arrays.toString(numArray)); //κλειδί προς αναζήτηση int key = 20; System.out.println("\nΚλειδί προς αναζήτηση=" + key); //ορισμός του πρώτου στον πρώτο δείκτη int first = 0; //ορισμός του τελευταίου στα τελευταία στοιχεία του πίνακα int last=numArray.length-1; //υπολογισμός του μέσου τηςarray int mid = (first + last)/2; //ενώ το πρώτο και το τελευταίο δεν επικαλύπτονται while( first <= last ){ //αν το mid <κλειδί, τότε το κλειδί προς αναζήτηση βρίσκεται στο πρώτο μισό του array if ( numArray[mid] last ){ System.out.println("Element is not found!"); } } }
Έξοδος:
Ο πίνακας εισόδου: [5, 10, 15, 20, 25, 30, 35]
Κλειδί προς αναζήτηση=20
Το στοιχείο βρίσκεται στο δείκτη: 3
Το παραπάνω πρόγραμμα δείχνει μια επαναληπτική προσέγγιση της δυαδικής αναζήτησης. Αρχικά, δηλώνεται ένας πίνακας και στη συνέχεια ορίζεται ένα κλειδί προς αναζήτηση.
Μετά τον υπολογισμό του μέσου του πίνακα, το κλειδί συγκρίνεται με το μέσο στοιχείο. Στη συνέχεια, ανάλογα με το αν το κλειδί είναι μικρότερο ή μεγαλύτερο από το κλειδί, το κλειδί αναζητείται στο κάτω ή στο άνω μισό του πίνακα αντίστοιχα.
Αναδρομική δυαδική αναζήτηση στη Java
Μπορείτε επίσης να εκτελέσετε δυαδική αναζήτηση χρησιμοποιώντας την τεχνική της αναδρομής. Εδώ, η μέθοδος δυαδικής αναζήτησης καλείται αναδρομικά μέχρι να βρεθεί το κλειδί ή να εξαντληθεί ολόκληρη η λίστα.
Το πρόγραμμα που υλοποιεί μια αναδρομική δυαδική αναζήτηση δίνεται παρακάτω:
import java.util.*; class Main{ //αναδρομική μέθοδος για δυαδική αναζήτηση public static int binary_Search(int int intArray[], int low, int high, int key){ //αν ο πίνακας είναι στη σειρά τότε εκτελούμε δυαδική αναζήτηση στον πίνακα if (high>=low){ //υπολογίζουμε το μέσο int mid = low + (high - low)/2; //αν key =intArray[mid] return mid if (intArray[mid] == key){ return mid; } //αν intArray[mid]> key τότε το κλειδί είναι στα αριστεράτο μισό του πίνακα if (intArray[mid]> key){ return binary_Search(intArray, low, mid-1, key);//αναδρομική αναζήτηση για το κλειδί }else //το κλειδί βρίσκεται στο δεξί μισό του πίνακα { return binary_Search(intArray, mid+1, high, key);//αναδρομική αναζήτηση για το κλειδί } } return -1; } public static void main(String args[]){ //ορισμός πίνακα και κλειδιού int intArray[] = {1,11,21,31,41,51,61,71,81,91}; System.out.println("InputΛίστα: " + Arrays.toString(intArray)); int key = 31; System.out.println("\nΤο κλειδί προς αναζήτηση:" + key); int high=intArray.length-1; //καλεί τη μέθοδο δυαδικής αναζήτησης int result = binary_Search(intArray,0,high,key); //εκτυπώνει το αποτέλεσμα if (result == -1) System.out.println("\nΚλειδί δεν βρέθηκε στη συγκεκριμένη λίστα!"); else System.out.println("\nΚλειδί βρέθηκε στη θέση: "+result + " στη λίστα"); } }
Έξοδος:
Κατάλογος εισόδου: [1, 11, 21, 31, 41, 51, 61, 71, 81, 91
Το κλειδί προς αναζήτηση:
Το κλειδί βρίσκεται στη θέση: 3 στη λίστα
Χρήση της μεθόδου Arrays.binarySearch ().
Η κλάση Arrays της Java παρέχει μια μέθοδο 'binarySearch ()' που εκτελεί τη δυαδική αναζήτηση στο δεδομένο Array. Η μέθοδος αυτή λαμβάνει ως ορίσματα τον πίνακα και το κλειδί προς αναζήτηση και επιστρέφει τη θέση του κλειδιού στον πίνακα. Εάν το κλειδί δεν βρεθεί, τότε η μέθοδος επιστρέφει -1.
Το παρακάτω παράδειγμα υλοποιεί τη μέθοδο Arrays.binarySearch ().
import java.util.Arrays; class Main{ public static void main(String args[]){ //ορίζουμε έναν πίνακα int intArray[] = {10,20,30,40,50,60,70,80,90}; System.out.println("Ο πίνακας εισόδου : " + Arrays.toString(intArray)); //ορίζουμε το κλειδί προς αναζήτηση int key = 50; System.out.println("\nΤο κλειδί προς αναζήτηση:" + key); //καλείται η μέθοδος binarySearch στον δεδομένο πίνακα με το κλειδί προς αναζήτηση int result =Arrays.binarySearch(intArray,key); //εκτυπώνουμε το αποτέλεσμα επιστροφής if (result <0) System.out.println("\nKey δεν βρέθηκε στον πίνακα!"); else System.out.println("\nKey βρέθηκε στον δείκτη: "+result + " στον πίνακα."); } }
Έξοδος:
Το Array εισόδου : [10, 20, 30, 40, 50, 60, 70, 80, 90]
Το κλειδί προς αναζήτηση:50
Το κλειδί βρίσκεται στον δείκτη: 4 στον πίνακα.
Συχνές ερωτήσεις
Q #1) Πώς γράφετε μια δυαδική αναζήτηση;
Απαντήστε: Η δυαδική αναζήτηση εκτελείται συνήθως διαιρώντας τον πίνακα σε μισά. Εάν το κλειδί που πρέπει να αναζητηθεί είναι μεγαλύτερο από το μεσαίο στοιχείο, τότε αναζητείται το άνω μισό του πίνακα με περαιτέρω διαίρεση και αναζήτηση του υποσυστήματος μέχρι να βρεθεί το κλειδί.
Ομοίως, αν το κλειδί είναι μικρότερο από το μεσαίο στοιχείο, τότε το κλειδί αναζητείται στο κάτω μισό του πίνακα.
Q #2) Πού χρησιμοποιείται η δυαδική αναζήτηση;
Απαντήστε: Η δυαδική αναζήτηση χρησιμοποιείται κυρίως για την αναζήτηση ταξινομημένων δεδομένων σε εφαρμογές λογισμικού, ιδίως όταν ο χώρος μνήμης είναι συμπαγής και περιορισμένος.
Q #3) Ποιο είναι το μεγάλο O της δυαδικής αναζήτησης;
Απαντήστε: Η χρονική πολυπλοκότητα της δυαδικής αναζήτησης είναι O (logn) όπου n είναι ο αριθμός των στοιχείων του πίνακα. Η πολυπλοκότητα χώρου της δυαδικής αναζήτησης είναι O (1).
Q #4) Είναι η δυαδική αναζήτηση αναδρομική;
Απαντήστε: Ναι. Δεδομένου ότι η δυαδική αναζήτηση είναι ένα παράδειγμα στρατηγικής διαίρει και βασίλευε και μπορεί να υλοποιηθεί με αναδρομή. Μπορούμε να χωρίσουμε τον πίνακα στα δύο και να καλέσουμε την ίδια μέθοδο για να εκτελέσουμε τη δυαδική αναζήτηση ξανά και ξανά.
Q #5) Γιατί ονομάζεται δυαδική αναζήτηση;
Απαντήστε: Ο αλγόριθμος δυαδικής αναζήτησης χρησιμοποιεί μια στρατηγική διαίρει και βασίλευε που κόβει επανειλημμένα τον πίνακα στα μισά ή σε δύο μέρη. Έτσι ονομάζεται δυαδική αναζήτηση.
Συμπέρασμα
Η δυαδική αναζήτηση είναι η συχνά χρησιμοποιούμενη τεχνική αναζήτησης στη Java. Η απαίτηση για την εκτέλεση μιας δυαδικής αναζήτησης είναι τα δεδομένα να είναι ταξινομημένα σε αύξουσα σειρά.
Μια δυαδική αναζήτηση μπορεί να υλοποιηθεί είτε με επαναληπτική είτε με αναδρομική προσέγγιση. Η κλάση Arrays της Java παρέχει επίσης τη μέθοδο 'binarySearch' που εκτελεί μια δυαδική αναζήτηση σε έναν Array.
Στα επόμενα σεμινάριά μας, θα εξερευνήσουμε διάφορες τεχνικές ταξινόμησης στη Java.