4.7 אלגוריתמים פתרון
תרגיל 1 - פתרון: מיון מערך של מספרים שלמים¶
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int arr[] = {42, 17, 8, 99, 3, 55, 21, 66};
int n = sizeof(arr) / sizeof(arr[0]);
printf("לפני: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
qsort(arr, n, sizeof(int), cmp);
printf("אחרי: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
תרגיל 2 - פתרון: מיון בסדר יורד¶
#include <stdio.h>
#include <stdlib.h>
int cmp_desc(const void *a, const void *b) {
return (*(int *)b - *(int *)a); // הפוך - b מינוס a
}
int main() {
int arr[] = {10, 40, 20, 50, 30};
int n = sizeof(arr) / sizeof(arr[0]);
printf("לפני: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
qsort(arr, n, sizeof(int), cmp_desc);
printf("אחרי: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
ההבדל היחיד מתרגיל 1 הוא שבפונקציית ההשוואה מחזירים b - a במקום a - b. ככה qsort ממיינת בסדר יורד במקום עולה.
תרגיל 3 - פתרון: מיון מערך של מחרוזות¶
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cmp_strings(const void *a, const void *b) {
const char *str_a = *(const char **)a;
const char *str_b = *(const char **)b;
return strcmp(str_a, str_b);
}
int main() {
char *names[] = {"Eve", "Alice", "Charlie", "Bob", "David"};
int n = sizeof(names) / sizeof(names[0]);
printf("לפני: ");
for (int i = 0; i < n; i++) {
printf("%s ", names[i]);
}
printf("\n");
qsort(names, n, sizeof(char *), cmp_strings);
printf("אחרי: ");
for (int i = 0; i < n; i++) {
printf("%s ", names[i]);
}
printf("\n");
return 0;
}
שימו לב לפונקציית ההשוואה: כי המערך הוא מערך של מצביעים (char *), הפרמטרים של פונקציית ההשוואה הם מצביעים למצביעים - כלומר char **. לכן עושים המרה ל-const char ** ואז dereference כדי לקבל את ה-char * עצמו.
תרגיל 4 - פתרון: חיפוש בינארי במערך ממוין¶
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int arr[] = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
int n = sizeof(arr) / sizeof(arr[0]);
printf("המערך: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
int target;
printf("הכנס מספר לחיפוש: ");
scanf("%d", &target);
int *found = bsearch(&target, arr, n, sizeof(int), cmp);
if (found != NULL) {
int index = found - arr; // חישוב האינדקס מהפרש מצביעים
printf("נמצא: %d באינדקס %d\n", *found, index);
} else {
printf("המספר %d לא נמצא במערך\n", target);
}
return 0;
}
חישוב האינדקס: כשמחסרים שני מצביעים מאותו טיפוס, התוצאה היא מספר האיברים ביניהם (לא מספר הבתים). לכן found - arr נותן לנו בדיוק את האינדקס של האיבר שנמצא.
תרגיל 5 - פתרון: מיון וחיפוש ביחד¶
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int arr[6];
printf("הכנס 6 מספרים: ");
for (int i = 0; i < 6; i++) {
scanf("%d", &arr[i]);
}
// מיון המערך
qsort(arr, 6, sizeof(int), cmp);
printf("מערך ממוין: ");
for (int i = 0; i < 6; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// חיפוש
int target;
printf("הכנס מספר לחיפוש: ");
scanf("%d", &target);
int *found = bsearch(&target, arr, 6, sizeof(int), cmp);
if (found != NULL) {
printf("נמצא: %d\n", *found);
} else {
printf("המספר %d לא נמצא\n", target);
}
return 0;
}
התוכנית הזו מדגימה את התבנית הנפוצה: קודם ממיינים עם qsort, ואז מחפשים עם bsearch. שתי הפונקציות משתמשות באותה פונקציית השוואה בדיוק - וזה לא במקרה, כי bsearch חייבת לדעת איך המערך ממוין כדי לבצע את החיפוש הבינארי נכון.