Οι αλγόριθμοι διαίρεσης και κυρίαρχίας (Divide and Conquer) είναι μια τεχνική επίλυσης προβλημάτων που χρησιμοποιεί τρία βασικά βήματα: διαίρεση, κατάκτηση και συνδυασμό. Ας αναλύσουμε αυτή την τεχνική πιο λεπτομερώς και στη συνέχεια ας δούμε δύο παραδείγματα για να κατανοήσουμε καλύτερα πώς λειτουργεί.
Τι είναι οι Αλγόριθμοι Διαίρεσης και Κυρίαρχίας;
Διαίρεση (Divide): Διαιρούμε το αρχικό πρόβλημα σε μικρότερα, πιο διαχειρίσιμα υποπροβλήματα. Αυτό μπορεί να γίνει διαχωρίζοντας τα δεδομένα ή τις εργασίες σε μέρη.
Κατάκτηση (Conquer): Λύνουμε τα υποπροβλήματα. Αν τα υποπροβλήματα είναι αρκετά μικρά, μπορούμε να τα λύσουμε άμεσα. Αν όχι, λύνουμε τα υποπροβλήματα αναδρομικά χρησιμοποιώντας την ίδια τεχνική διαίρεσης και κυρίαρχίας.
Συνδυασμός (Combine): Συνδυάζουμε τις λύσεις των υποπροβλημάτων για να πάρουμε τη λύση του αρχικού προβλήματος. Ο τρόπος συνδυασμού εξαρτάται από το συγκεκριμένο πρόβλημα.
Ας δούμε δύο κλασικά παραδείγματα αλγορίθμων διαίρεσης και κυρίαρχίας: τη Δυαδική Αναζήτηση και την Ταξινόμηση Συγχώνευσης.
Παράδειγμα 1: Δυαδική Αναζήτηση (Binary Search)
Η δυαδική αναζήτηση χρησιμοποιείται για να βρούμε ένα στοιχείο σε έναν ταξινομημένο πίνακα. Χρησιμοποιεί την τεχνική διαίρεσης και κυρίαρχίας διαιρώντας τον πίνακα στο μέσο του και ελέγχοντας σε ποιο μέρος πρέπει να συνεχίσει την αναζήτηση
Διαδικασία Δυαδική_Αναζήτηση(πίνακας, αριστερά, δεξιά, κλειδί)
Αν αριστερά > δεξιά τότε
Επιστροφή -1
Τέλος_αν
μεσαίο <- (αριστερά + δεξιά) // 2
Αν πίνακας[μεσαίο] = κλειδί τότε
Επιστροφή μεσαίο
Αλλιώς_αν πίνακας[μεσαίο] > κλειδί τότε
Επιστροφή Δυαδική_Αναζήτηση(πίνακας, αριστερά, μεσαίο - 1, κλειδί)
Αλλιώς
Επιστροφή Δυαδική_Αναζήτηση(πίνακας, μεσαίο + 1, δεξιά, κλειδί)
Τέλος_αν
Τέλος_Διαδικασίας
C# Κώδικας
using System;
class Program
{
static void Main()
{
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int key = 7;
int result = BinarySearch(array, 0, array.Length - 1, key);
if (result != -1)
{
Console.WriteLine($"Element {key} found at index: {result}");
}
else
{
Console.WriteLine($"Element {key} not found in the array.");
}
}
static int BinarySearch(int[] array, int left, int right, int key)
{
if (left > right)
{
return -1;
}
int middle = (left + right) / 2;
if (array[middle] == key)
{
return middle;
}
else if (array[middle] > key)
{
return BinarySearch(array, left, middle - 1, key);
}
else
{
return BinarySearch(array, middle + 1, right, key);
}
}
}
Παράδειγμα 2: Ταξινόμηση Συγχώνευσης (Merge Sort)
Η ταξινόμηση συγχώνευσης χρησιμοποιείται για να ταξινομήσουμε έναν πίνακα. Χρησιμοποιεί την τεχνική διαίρεσης και κυρίαρχίας διαιρώντας τον πίνακα σε μικρότερα τμήματα, τα οποία ταξινομούνται και στη συνέχεια συγχωνεύονται για να δημιουργήσουν τον τελικό ταξινομημένο πίνακα.
Ψευδογλώσσα
Διαδικασία Ταξινόμηση_Συγχώνευσης(πίνακας)
Αν πίνακας.μήκος <= 1 τότε
Επιστροφή πίνακας
Τέλος_αν
μέση <- πίνακας.μήκος // 2
αριστερός_πίνακας <- πίνακας[0...μέση-1]
δεξιός_πίνακας <- πίνακας[μέση...τέλος]
αριστερός_πίνακας <- Ταξινόμηση_Συγχώνευσης(αριστερός_πίνακας)
δεξιός_πίνακας <- Ταξινόμηση_Συγχώνευσης(δεξιός_πίνακας)
Επιστροφή Συγχώνευση(αριστερός_πίνακας, δεξιός_πίνακας)
Τέλος_Διαδικασίας
Διαδικασία Συγχώνευση(αριστερός_πίνακας, δεξιός_πίνακας)
αποτέλεσμα <- νέος πίνακας
όσο αριστερός_πίνακας δεν είναι άδειος και δεξιός_πίνακας δεν είναι άδειος
αν αριστερός_πίνακας[0] < δεξιός_πίνακας[0] τότε
προσθήκη αριστερός_πίνακας[0] στο αποτέλεσμα
αφαίρεση αριστερός_πίνακας[0]
αλλιώς
προσθήκη δεξιός_πίνακας[0] στο αποτέλεσμα
αφαίρεση δεξιός_πίνακας[0]
Τέλος_αν
Τέλος_όσο
προσθήκη των υπολοίπων στοιχείων του αριστερού_πίνακα στο αποτέλεσμα
προσθήκη των υπολοίπων στοιχείων του δεξιού_πίνακα στο αποτέλεσμα
Επιστροφή αποτέλεσμα
Τέλος_Διαδικασίας
C# Κώδικας
using System;
class Program
{
static void Main()
{
int[] array = { 38, 27, 43, 3, 9, 82, 10 };
MergeSort(array);
Console.WriteLine("Sorted array: " + string.Join(", ", array));
}
static void MergeSort(int[] array)
{
if (array.Length <= 1)
return;
int mid = array.Length / 2;
int[] left = new int[mid];
int[] right = new int[array.Length - mid];
Array.Copy(array, 0, left, 0, mid);
Array.Copy(array, mid, right, 0, array.Length - mid);
MergeSort(left);
MergeSort(right);
Merge(array, left, right);
}
static void Merge(int[] array, int[] left, int[] right)
{
int i = 0, j = 0, k = 0;
while (i < left.Length && j < right.Length)
{
if (left[i] <= right[j])
{
array[k++] = left[i++];
}
else
{
array[k++] = right[j++];
}
}
while (i < left.Length)
{
array[k++] = left[i++];
}
while (j < right.Length)
{
array[k++] = right[j++];
}
}
}