【C語言】剖析qsort函數的實現原理

主頁: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)的標準庫函數。它接受一個數組和一個比較函數作為參數,并對數組進行排序。快速排序是一種分治的排序算法,通過選擇一個基準元素,將數組分為兩部分,一部分比基準元素小,一部分比基準元素大,然后對這兩部分遞歸地進行排序,最終得到一個有序的數組。

實現原理

  1. 選擇基準元素qsort?函數首先選擇數組中的一個元素作為基準元素。通常情況下,可以選擇數組的第一個元素作為基準元素。

  2. 分區(Partition)qsort?函數使用選定的基準元素將數組分為兩部分,一部分小于等于基準元素,另一部分大于基準元素。這個過程稱為分區。

  3. 遞歸排序qsort?函數遞歸地對小于等于基準元素和大于基準元素的兩部分進行排序。它分別對這兩部分調用?qsort?函數,并將相應的比較函數傳遞給子函數。

  4. 合并結果:最后,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函數實現,通過選擇一個基準元素,并將數組分成兩部分,使得左邊的元素都小于或等于基準元素,而右邊的元素都大于基準元素,然后對左右兩部分遞歸地進行排序,最終得到一個有序的數組。

以下是各個函數的分解解析:

  1. swap?函數:這個函數用于交換兩個整數的值。它接受兩個整數指針作為參數,并使用?temp?變量來暫存其中一個整數的值,然后將兩個整數的值進行交換。
  2. partition?函數:這個函數用于將一個數組的某個子數組分成兩部分,使得左邊的元素都小于或等于基準元素,而右邊的元素都大于基準元素。它接受一個整數數組、子數組的起始索引和結束索引作為參數。首先,它選擇最后一個元素作為基準元素,并將?i?初始化為?low - 1。然后,它使用一個循環從?low?到?high - 1?遍歷數組,如果當前元素小于基準元素,就將?i?向右移動一個位置,并將當前元素和?arr[i]?進行交換。最后,它將基準元素和?arr[i + 1]?進行交換,使得基準元素位于正確的位置上。
  3. quickSort?函數:這個函數用于對一個數組進行快速排序。它接受一個整數數組和起始索引和結束索引作為參數。如果起始索引小于結束索引,它就調用?partition?函數將數組分成兩部分,并對左右兩部分遞歸地進行排序。
  4. myQsort?函數:這個函數是一個封裝的快速排序函數,它接受一個整數數組和數組的大小作為參數,并調用?quickSort?函數對數組進行排序。
  5. main?函數:這個函數是程序的入口函數。它首先定義了一個整數數組?arr,并計算數組的大小。然后,它調用?myQsort?函數對數組進行排序,并打印排序后的結果。

?

本篇博客到此就結束啦~

如果有幫助到您的學習是我的無上榮幸!

感謝閱讀!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718366.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718366.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718366.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql主從庫Slave_SQL_Running: No問題經驗分享

最近在創建mysql主從庫的時候&#xff0c;遇到一個問題。執行 mysql> SHOW SLAVE STATUS\G結果顯示 Slave_IO_Running: Yes Slave_SQL_Running: No 很是苦惱&#xff0c;查詢了很久沒有解決 執行 mysql> SELECT * FROM performance_schema.replication_applier_status_…

獨立游戲《星塵異變》UE5 C++程序開發日志1——項目與代碼管理

寫在前面&#xff1a;本日志系列將會向大家介紹在《星塵異變》這款模擬經營游戲&#xff0c;在開發時用到的與C相關的泛用代碼與算法&#xff0c;主要記錄UE5C與原生C的用法區別&#xff0c;以及遇到的問題和解決辦法&#xff0c;因為這是我本人從ACM退役以后第一個從頭開始的項…

代碼隨想錄算法訓練營第五十天 | 買股票2

目錄 買賣股票的最佳時機III買賣股票的最佳時機IV LeetCode 123.買賣股票的最佳時機III LeetCode 123.買賣股票的最佳時機IV 買賣股票的最佳時機III 給定一個數組&#xff0c;它的第 i 個元素是一支給定的股票在第 i 天的價格。 設計一個算法來計算你所能獲取的最大利潤。…

牛客周賽 Round 35(A,B,C,D,E,F,G)

這場簡單&#xff0c;甚至賽時90分鐘不到就AK了。比賽鏈接&#xff0c;隊友題解友鏈 剛入住學校監獄&#xff0c;很不適應&#xff0c;最近難受的要死&#xff0c;加上最近幾場CF打的都不順利&#xff0c;san值要爆掉了&#xff0c;只能慢慢補題了。 這場C是個滑動窗口&#…

冒泡排序 和 qsort排序

目錄 冒泡排序 冒泡排序部分 輸出函數部分 主函數部分 總代碼 控制臺輸出顯示 總代碼解釋 冒泡排序優化 冒泡排序 主函數 總代碼 代碼優化解釋 qsort 排序 qsort 的介紹 使用qsort排序整型數據 使用qsort排序結構數據 冒泡排序 首先&#xff0c;我先介紹我的冒泡…

模糊搜索小案例

C#窗體實現數據錄入與模糊搜索小案例 記錄一下 主要代碼 private void button1_Click(object sender, EventArgs e){string name textBox1.Text;string hometown textBox4.Text;string school textBox6.Text;string sex textBox5.Text;string lat textBox3.Text;string …

c#打印BarTend標簽提示:具名數據源沒有cuckoo*具名數據(解決)

c#打印BarTend標簽提示&#xff1a;具名數據源沒有cuckoo*具名數據&#xff08;解決&#xff09; 今天咕咕更新打印模板的時候遇到的問題&#xff0c;就是在模版中配置了字段名&#xff0c;但是啟動c#應用&#xff0c;后端發送json數據打印的時候c#報錯提示&#xff0c;沒有在…

python 小游戲《2048》字符版非圖形界面

參考鏈接&#xff1a; 閑談2048小游戲和數組的旋轉及翻轉和轉置 目錄 2048 一、方陣類 二、隨機插入1或2 三、 合并和遞增 四、 判斷和移動 五、 鍵盤控制 完整源代碼 玩法過程 2048 上回說到2048小游戲中數組的各種旋轉、翻轉的方法&#xff0c;就是為代碼編程作準…

第十六天-爬蟲selenium庫

目錄 1.介紹 2.使用 selenium 1.安裝 2.使用 1.測試打開網頁&#xff0c;抓取雷速體育日職乙信息 2.通過xpath查找 3.輸入文本框內容 send_keys 4.點擊事件 click 5.獲取網頁源碼&#xff1a; 6.獲取cookies 7.seleniumt提供元素定位方式&#xff1a;8種 8.控制瀏覽…

Spring Security OAuth2如何自定義返回的 Token 信息

文章目錄 Spring Security OAuth2如何自定義返回的 Token 信息定制不透明令牌的信息Springsecurity-oauth2之TokenEndPoint參考Spring Security OAuth2如何自定義返回的 Token 信息 Spring Boot+OAuth2,如何自定義返回的 Token 信息? 參考URL: https://www.jianshu.com/p/b7…

【Go】指針的聲明和初始化

package mainimport "fmt"func main() {// 聲明一個整數變量var num int 42// 聲明一個指向整數的指針變量&#xff0c;并將其初始化為指向整數變量的地址var ptr *int &num// 打印整數變量的值和指針變量的值&#xff08;即整數變量的地址&#xff09;fmt.Pri…

2024第24屆中國國際工業博覽會新能源與智能網聯汽車展電池制造展館

2024第24屆中國國際工業博覽會新能源與智能網聯汽車展電池制造展館 時間&#xff1a;2024年9月24日-28日 地點&#xff1a;國家會展中心&#xff08;上海&#xff09; 主辦單位&#xff1a;工業和信息化部、國家發展和改革委員會、科學技術部、商務部、中國科學院、中國工程…

【游記】GDOI2024

GDOI2024游記 老年退役選手。NOIP 218 分&#xff0c;GDOI 純純旅游。 Day -5 周日返校&#xff0c;開始停課。 開始攢 rp。 Day -4 模擬賽&#xff0c;犯困&#xff0c;啥也不會。 下午打球。 Day -3 模擬賽&#xff0c;不困&#xff0c;還是啥也不會。 下午打球。 …

CSS3單獨制作移動端頁面布局方式(流式布局、flex彈性布局)

目錄 1. 流式布局(百分比布局)2. flex彈性布局(強烈推薦)2.1 介紹2.2 Flex容器常見屬性2.2.1 flex-direction2.2.2 justify-content2.2.3 flex-wrap2.2.4 align-items2.2.5 align-content2.2.6 flex-flow 2.3 Flex項目常見屬性2.3.1 flex2.3.2 align-self和order 1. 流式布局(百…

銀河麒麟之Workstation安裝

一、VMware Workstation簡介 VMware Workstation是一款由VMware公司開發的虛擬化軟件&#xff0c;它允許用戶在一臺物理計算機上運行多個操作系統&#xff0c;并在每個操作系統中運行多個虛擬機。VMware Workstation提供了一個可視化的用戶界面&#xff0c;使用戶可以輕松創建、…

程序環境和預處理(2)

文章目錄 3.2.7 命名約定 3.3 #undef3.4 命令行定義3.5 條件編譯3.6 文件包含3.6.1 頭文件被包含的方式3.6.2 嵌套文件包含 4. 其他預處理指令 3.2.7 命名約定 一般來講函數和宏的使用語法很相似&#xff0c;所以語言本身沒法幫我們區分二者&#xff0c;那我們平時的一個習慣是…

linux條件判斷之if-then

if..then是最常見的條件判斷語句&#xff0c;簡而言之&#xff0c;就是當符合某個條件判斷的時候&#xff0c;就予以進行某項工作。 1.if-then格式 if-then格式1&#xff1a; if [ 條件判斷表達式 ];then 當條件判斷表達式成立時&#xff0c;需執行的命令 fi if-then格式2…

Redis安全加固策略:綁定Redis監聽的IP地址 修改默認端口 禁用或者重命名高危命令

Redis安全加固策略&#xff1a;綁定Redis監聽的IP地址 & 修改默認端口 & 禁用或者重命名高危命令 1.1 綁定Redis監聽的IP地址1.2 修改默認端口1.3 禁用或者重命名高危命令1.4 附&#xff1a;redis配置文件詳解&#xff08;來源于網絡&#xff09; &#x1f496;The Beg…

驅動開發面試復習

創建字符設備 1 創建設備號 alloc_chrdev_region 2.創建cdev cdev_init 3.添加一個 cdev,完成字符設備注冊到內核 cdev_add 4.創建類 class_create 5.創建設備 device_create 1.內核空間與用戶空間數據 copy_from_user 和copy_to_user 倆個函數來完成。 copy_from_user 函數…

618快遞準點到達,別忘了感謝它!

進入6月以來&#xff0c;全國快遞日均業務量飛速上漲。 雖然618大促是電商的主場&#xff0c;但作為不可或缺的物流環節&#xff0c;為了這場年中大考&#xff0c;快遞企業在此期間也使盡渾身解數&#xff0c;競相比拼配送速度。那么&#xff0c;為了更快的時效&#xff0c;快遞…