主頁:17_Kevin-CSDN博客
專欄:《C語言》
本文將從回調函數,qsort函數的應用,qsort函數的實現原理三個方面進行講解,請自行跳轉至相對位置進行閱讀~?
目錄
回調函數
qsort函數的應用
qsort函數實現原理
回調函數
什么是回調函數?
回調函數實際上是一個指針,指向的是一個函數。它作為一個參數傳遞給另一個函數,并且在特定的條件下被執行。
回調函數的作用
回調函數的主要作用是使代碼更加靈活和模塊化。通過使用回調函數,我們可以將特定的行為或邏輯與原始函數分離開來,這樣可以讓我們更容易地進行代碼重用和維護。
回調函數的實現
定義一個函數,然后將其作為參數傳遞給其他函數,在特定條件下執行
回調函數的示例
讓我們以 C 語言為例,來看一個簡單的回調函數示例:
#include <stdio.h>void performOperation(int a, int b, int (*callback)(int, int))
{int result = callback(a, b);printf("The result is: %d\n", result);
}int add(int a, int b)
{return a + b;
}int main()
{int x = 10, y = 20;performOperation(x, y, add); // 傳遞 add 函數作為回調函數return 0;
}
在這個示例中,performOperation 函數接受兩個整數和一個函數指針作為參數,然后在內部調用傳遞進來的函數指針,實現了加法運算。在主函數中,我們將 add 函數作為回調函數傳遞給 performOperation 函數。這就是一個簡單的回調函數的例子。
qsort函數的應用
函數定義
在官方文檔中qsort的函數定義如下:
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
函數參數的剖析
base:
參數base是一個void* 類型的,qsor使用來排序的函數,該參數就是傳入的要進行排序的數組。作為一個void*類型的指針,我們傳入數組的地址,即可完成對要排序數組的傳入。
num:
該參數位置要傳入的是要進行排序的數組的元素個數,一般使用sizeof(數組名)/ sizeof(數組中的任意元素)進行計算得到個數。
size:
參數size傳入的參數是數組中單個元素的大小,該參數可以確保在函數內排序的時候每次跳躍的字節大小是一個元素的字節的大小。
compar:
該參數是一個函數指針,指向比較兩個元素的函數。 qsort內部會反復調用此函數來比較兩個元素,以此來決定排序方向。請注意!在傳入該參數的時候請嚴格按照該參數的規范結構來書寫。
int (*compar)(const void*,const void*)
為什么要用void*?
這是因為
qsort
函數可以對任意類型的數組進行排序,而不同類型的數據可能需要不同的比較方法。使用void*
類型作為參數可以讓比較函數更加通用,因為void*
是一種無類型指針,可以指向任何類型的數據。在比較函數內部,我們可以將void*
類型的指針轉換為實際的數據類型再進行比較(強制類型轉化)。通過使用
void*
類型,可以在不知道具體數據類型的情況下編寫通用的比較函數,使qsort
函數更加靈活和通用。在比較函數中,我們需要負責將void*
類型的指針轉換為實際的數據類型,并進行比較操作。使用
void*
類型的參數可以使比較函數更加通用,適用于不同類型的數據,從而增強了函數的靈活性和通用性。
經典代碼示例
#include <stdio.h>
#include <stdlib.h>// 比較函數,用于升序排序
int compare(const void *a, const void *b) {return (*(int*)a - *(int*)b);
}int main() {int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};int n = sizeof(arr) / sizeof(arr[0]);// 使用 qsort 對數組進行排序qsort(arr, n, sizeof(int), compare);printf("Sorted array: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}
在這個示例中,首先定義了一個整型數組 arr
,然后通過 qsort
函數對數組進行排序。在 main
函數中,我們計算數組的大小 n
,然后調用 qsort
函數,傳入數組、數組大小、每個元素的大小以及比較函數 compare
。比較函數 compare
中,我們將 void*
類型的指針轉換為 int*
類型,并進行升序排序。最終得到的就是升序排序的數組了。
qsort函數實現原理
詳細定義
qsort
?函數是一個用于快速排序(Quick Sort)的標準庫函數。它接受一個數組和一個比較函數作為參數,并對數組進行排序。快速排序是一種分治的排序算法,通過選擇一個基準元素,將數組分為兩部分,一部分比基準元素小,一部分比基準元素大,然后對這兩部分遞歸地進行排序,最終得到一個有序的數組。
實現原理
選擇基準元素:
qsort
?函數首先選擇數組中的一個元素作為基準元素。通常情況下,可以選擇數組的第一個元素作為基準元素。分區(Partition):
qsort
?函數使用選定的基準元素將數組分為兩部分,一部分小于等于基準元素,另一部分大于基準元素。這個過程稱為分區。遞歸排序:
qsort
?函數遞歸地對小于等于基準元素和大于基準元素的兩部分進行排序。它分別對這兩部分調用?qsort
?函數,并將相應的比較函數傳遞給子函數。合并結果:最后,
qsort
?函數將排序后的兩部分合并起來,形成一個有序的數組。
模擬實現sort
以下代碼使用C語言模擬實現qsort函數的代碼:
#include <stdio.h>void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}int partition(int arr[], int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j <= high - 1; j++) {if (arr[j] < pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return i + 1;
}void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}void myQsort(int arr[], int n) {quickSort(arr, 0, n - 1);
}int main() {int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};int n = sizeof(arr) / sizeof(arr[0]);myQsort(arr, n);printf("Sorted array: ");for (int i = 0; i < n; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}
這是一個以快速排序為基礎的qsort函數實現,通過選擇一個基準元素,并將數組分成兩部分,使得左邊的元素都小于或等于基準元素,而右邊的元素都大于基準元素,然后對左右兩部分遞歸地進行排序,最終得到一個有序的數組。
以下是各個函數的分解解析:
swap
?函數:這個函數用于交換兩個整數的值。它接受兩個整數指針作為參數,并使用?temp
?變量來暫存其中一個整數的值,然后將兩個整數的值進行交換。partition
?函數:這個函數用于將一個數組的某個子數組分成兩部分,使得左邊的元素都小于或等于基準元素,而右邊的元素都大于基準元素。它接受一個整數數組、子數組的起始索引和結束索引作為參數。首先,它選擇最后一個元素作為基準元素,并將?i
?初始化為?low - 1
。然后,它使用一個循環從?low
?到?high - 1
?遍歷數組,如果當前元素小于基準元素,就將?i
?向右移動一個位置,并將當前元素和?arr[i]
?進行交換。最后,它將基準元素和?arr[i + 1]
?進行交換,使得基準元素位于正確的位置上。quickSort
?函數:這個函數用于對一個數組進行快速排序。它接受一個整數數組和起始索引和結束索引作為參數。如果起始索引小于結束索引,它就調用?partition
?函數將數組分成兩部分,并對左右兩部分遞歸地進行排序。myQsort
?函數:這個函數是一個封裝的快速排序函數,它接受一個整數數組和數組的大小作為參數,并調用?quickSort
?函數對數組進行排序。main
?函數:這個函數是程序的入口函數。它首先定義了一個整數數組?arr
,并計算數組的大小。然后,它調用?myQsort
?函數對數組進行排序,并打印排序后的結果。
?
本篇博客到此就結束啦~
如果有幫助到您的學習是我的無上榮幸!
感謝閱讀!