運用qsort函數進行快排并使用C語言模擬qsort

qsort 函數的使用

? ? ? ?首先qsort函數是使用快速排序算法來進行排序的,下面我們打開官網來查看qsort是如何使用的。


這里有四個參數,首先base 是至待排序的數組的首元素的地址,num 是值這個數組的元素個數,size 是指每個元素的大小,最后是一個函數指針(用來比較兩個元素的不同,其中這個函數需要有返回值,當返回值小于0時p1需要放在p2前面,等于0時p1和p2不用改變位置,當返回值大于0時,p1需要放在p2的后面)由此可見,這個函數需要我們自己去編寫,然后通過函數指針來調用。

下面我們來看看qsort的實踐效果:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct Stu
{char name[20];int age;
}Stu;int cmp_array(const void* p1,const void* p2)
{return *(int*)p1 - *(int*)p2;
}int cmp_stu_name(const void* p1, const void* p2)
{return strcmp(((Stu*)p1)->name, ((Stu*)p2)->name);
}int cmp_stu_age(const void* p1, const void* p2)
{return ((Stu*)p1)->age - ((Stu*)p2)->age;
}void PrintArray(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}void PrintStu(Stu* s, int sz)
{for (int i = 0; i < sz; i++){printf("%s %d", s[i].name, s[i].age);printf("\n");}
}int main()
{Stu s[3] = { {"zhangsan",18},{"lisi",19},{"sunwu",15} };int sz = sizeof(s) / sizeof(s[0]);int arr[10] = { 4,8,5,7,9,6,2,0,1,3 };int sz2 = sizeof(arr) / sizeof(arr[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_name);PrintStu(s, sz);printf("\n");qsort(s, sz, sizeof(s[0]), cmp_stu_age);PrintStu(s, sz);printf("\n");qsort(arr, sz2, sizeof(arr[0]), cmp_array);PrintArray(arr, sz2);printf("\n");return 0;
}

使用C語言模擬qsort

? ? ? ?這里我們使用冒泡排序算法進行排序,使用C語言來模擬qsort函數。
? ? ? ?首先我們來回顧冒泡排序算法,有兩個要點一個是排序的趟數,另一個是每一趟排序的次數。這里以升序為例:

void bubble_sort(int arr[], int sz)
{for (int i = 0; i < sz - 1; i++){for (int j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}

然后來模擬qsort函數呢?首先qsort函數幾乎對任何數據都可以排序,所以我們的bubble_sort函數要做出相應調整,然后設計形參呢?對任何數據進行排序,也就是說數據的類型和大小都是不確定的,這樣的話,我們可以使用size_t來作為數據類型,用void來接收不同類型的指針,實在不會的,我們可以參考qsort 函數來設計的。

void
base 接收待排序的首元素的地址,size_t num 和 size_t size 來接收元素個數和元素大小,最后就是最重要的函數設計了。

void bubble_sort(void* base, size_t num, size_t size, int (*compar) (const void* p1, const void* p2))

設計好形參,我們來考慮一下函數的主體部分,首先趟數是不改變的,每趟的次數也不用改變,畢竟我們還是使用冒泡排序算法,這樣的話,還有最后一個就是if這個判斷語句,應為我們無法直接通過像上面一樣對兩個數進行直接比較,我們需要調用函數來進行比較,也就是compar函數。

那有個問題,我們如何來寫compar 函數的指針呢?這個指針不能大也不能小,否則就無法準確比較或者會產生越界行為,這樣我們可以使用char* 為什么呢?首先我們需要兩個兩個數據來進行一一比較,這樣我們需要知道準確的地址,必須是恰好指向每個元素的地址,而char 剛好就是一個字節,只要準確地進行指針加法運算就能得到這個元素地地址。

if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0)

還有個問題,我們怎么交換數據呢?其實和上面的理由差不多由于數據的類型不同,他們的大小也不同。這時我們可以使用char 因為char 是最小的數據類型了,也就是一個字節,無論數據是幾個字節,都是char 的倍數也就是說都可以用一個字節的倍數來表示,這樣的話,我們只需要知道數據類型的大小(size) 就可以來通過循環遍歷來一個字節一個字節來進行進行交換就可以了,我們可以封裝一個函數swap。

void swap(char* p1, char* p2, size_t size)
{int i = 0;while (i < size){char tmp = *(p1 + i);*(p1 + i) = *(p2 + i);*(p2 + i) = tmp;i++;}
}

那么我們最后得到的bubble_sort函數如下:

void bubble_sort(void* base, size_t num, size_t size, int (*compar) (const void* p1, const void* p2))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0){swap((char*)base + j * size, (char*)base + (j + 1) * size);}}}
}

我們來演練一下,看看效果是不是和qsort有著一樣的效果:

代碼如下:

#include <stdio.h>
#include <string.h>typedef struct Stu
{char name[20];int age;
}Stu;int cmp_array(const void* p1,const void* p2)
{return *(int*)p1 - *(int*)p2;
}int cmp_stu_name(const void* p1, const void* p2)
{return strcmp(((Stu*)p1)->name, ((Stu*)p2)->name);
}int cmp_stu_age(const void* p1, const void* p2)
{return ((Stu*)p1)->age - ((Stu*)p2)->age;
}void PrintArray(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}void PrintStu(Stu* s, int sz)
{for (int i = 0; i < sz; i++){printf("%s %d", s[i].name, s[i].age);printf("\n");}
}void swap(char* p1, char* p2, size_t size)
{int i = 0;while (i < size){char tmp = *(p1 + i);*(p1 + i) = *(p2 + i);*(p2 + i) = tmp;i++;}
}void bubble_sort(void* base, size_t num, size_t size, int (*compar) (const void* p1, const void* p2))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (compar((char*)base + j * size, (char*)base + (j + 1) * size) > 0){swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}int main()
{Stu s[3] = { {"zhangsan",18},{"lisi",19},{"sunwu",15} };int sz = sizeof(s) / sizeof(s[0]);int arr[10] = { 4,8,5,7,9,6,2,0,1,3 };int sz2 = sizeof(arr) / sizeof(arr[0]);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_name);PrintStu(s, sz);printf("\n");bubble_sort(s, sz, sizeof(s[0]), cmp_stu_age);PrintStu(s, sz);printf("\n");bubble_sort(arr, sz2, sizeof(arr[0]), cmp_array);PrintArray(arr, sz2);printf("\n");return 0;
}

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

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

相關文章

Python猜數字小游戲

下面這段代碼是一個簡單的數字猜測游戲&#xff0c;其中計算機已經提前計算出了414 // 23的結果并存儲在變量num中。然后&#xff0c;程序會提示用戶來猜測這個結果。 以下是代碼的主要步驟和功能&#xff1a; 初始化&#xff1a; num 414 // 23&#xff1a;計算414除以23的整…

Linux:各目錄含義

簡介 學習Linux各目錄含義之前&#xff0c;我們首先要了解一下Filesystem Hierarchy Standard&#xff08;文件系統層次結構標準&#xff09;。 FHS FHS&#xff0c;即文件系統層次結構標準&#xff08;Filesystem Hierarchy Standard&#xff09;&#xff0c;是Linux和類Un…

深入了解Redis:配置文件、動態修改和安全設置

Redis 是一個開源的內存中數據結構存儲系統&#xff0c;它可以用作數據庫、緩存和消息中間件。在使用 Redis 時&#xff0c;了解其配置選項是至關重要的。本文將詳細介紹 Redis 的配置文件和常用配置項&#xff0c;并提供一些示例來說明如何設置和修改這些配置。 Redis 配置文…

基于stm32F103的座面聲控臺燈

1.基本內容&#xff1a; 設計一個放置在桌面使用的臺燈&#xff0c;使用220v交流電供電。具備顯示屏能夠實時顯示日期&#xff08;年、月、日和星期&#xff09;&#xff0c;時間&#xff08;小時、分鐘、秒&#xff09;和溫度&#xff08;攝氏度&#xff09;&#xff1b;能夠通…

Python爬取天氣數據及可視化分析!(含源碼)

天氣預報我們每天都會關注&#xff0c;我們可以根據未來的天氣增減衣物、安排出行&#xff0c;每天的氣溫、風速風向、相對濕度、空氣質量等成為關注的焦點。本次使用python中requests和BeautifulSoup庫對中國天氣網當天和未來14天的數據進行爬取&#xff0c;保存為csv文件&…

帆軟下載PDF報錯java.lang.OutOfMemoryError: Java heap space

需求:前端選擇多條數據&#xff0c;點擊下載按鈕&#xff0c;下載帆軟報表的pdf格式。 &#xff08;目前用的是帆軟PDF下載接口&#xff0c;然后java轉成文件流&#xff0c;前端接到后端接口的文件流&#xff0c;使用axios下載blob,再創建下載鏈接&#xff0c;通過link標簽實現…

ArduinoTFTLCD應用

ArduinoTFTLCD應用 ArduinoTFTLCD應用硬件連接軟件導入庫顯示數字、字符顯示漢字方案1方案2 顯示圖片 總結 ArduinoTFTLCD應用 對于手工喜歡DIY的人來說&#xff0c;Arduino驅動的TFTLCD被很多人使用&#xff0c;此處就總結一下&#xff0c;使用的是VScode的PlatformIO插件驅動…

C# API異步方法和返回類型:提升應用程序性能和靈活性

摘要&#xff1a; 異步編程是現代應用程序開發中不可或缺的一部分。在C#中&#xff0c;異步方法允許我們在等待操作完成時繼續執行其他任務&#xff0c;從而提高應用程序的性能和響應性。本文將介紹C# API異步方法的基本概念、原理和實際應用&#xff0c;并詳細討論異步方法的返…

【機器學習】實驗5,AAAI 會議論文聚類分析

本次實驗以AAAI 2014會議論文數據為基礎&#xff0c;要求實現或調用無監督聚類算法&#xff0c;了解聚類方法。 任務介紹 每年國際上召開的大大小小學術會議不計其數&#xff0c;發表了非常多的論文。在計算機領域的一些大型學術會議上&#xff0c;一次就可以發表涉及各個方向…

RNA-Seq 筆記 [4]

***********************該筆記為初學者筆記&#xff0c;僅供個人參考謹慎搬運代碼****************************** samtools 排序壓縮和 featureCounts 生成基因計數表 SAM文件和BAM文件 1.SAM格式&#xff1a;是一種通用的比對格式&#xff0c;用來存儲reads到參考序列的比…

2024最新算法:鳑鲏魚優化算法(Bitterling Fish Optimization,BFO)求解23個基準函數(提供MATLAB代碼)

一、鳑鲏魚優化算法 鳑鲏魚優化算法&#xff08;Bitterling Fish Optimization&#xff0c;BFO&#xff09;由Lida Zareian 等人于2024年提出。鳑鲏魚在交配中&#xff0c;雄性和雌性物種相互接近&#xff0c;然后將精子和卵子釋放到水中&#xff0c;但這種方法有一個很大的缺…

BUUCTF---[極客大挑戰 2019]Upload1

1.題目描述 2.點開鏈接&#xff0c;需要上傳文件&#xff0c;要求是image&#xff0c;上傳文件后綴為jpg的一句話木馬&#xff0c;發現被檢測到了 3.換另一個木馬試試 GIF89a? <script language"php">eval($_REQUEST[1])</script> 發現可以上傳成功 4…

ctf_show筆記篇(web入門---文件包含)

目錄 文件包含 78-79&#xff1a;最基礎的文件包含&#xff0c;使用偽協議&#xff0c;大小寫繞過或者通配符繞過&#xff0c;再或者使用其他方法 ?編輯80-81&#xff1a;可采用日志文件繞過或者大小寫繞過&#xff08;81只能日志文件繞過&#xff09; ####80-86&#xff1…

『周年紀念』- 降生CSDN三周年的碎碎念

『周年紀念』- 降生CSDN三周年的碎碎念 緣起機緣迷茫厚積薄發 一轉眼又過來一年&#xff0c;自己也已經 大四即將畢業。 感覺這一年像是開了加速鍵&#xff0c;仿佛一瞬就又過去了。統計了一下發現自己在過去的這一年就發布了 2篇文章&#xff0c;2022年發布了 117篇&#x…

PDF 解析問題調研

說點真實的感受 &#xff1a;網上看啥組件都好&#xff0c;實際測&#xff0c;啥組件都不行。效果好的不開源收費&#xff0c;開源的效果不好。測試下來&#xff0c;發現把組件融合起來&#xff0c;還是能不花錢解決問題的&#xff0c;都是麻煩折騰一些。 這里分享了目前網上能…

Python中的反射

在Python中&#xff0c;反射&#xff08;Reflection&#xff09;是一種動態地訪問對象和調用其方法的能力&#xff0c;而不需要在編寫代碼時顯式地知道對象的類或屬性。這種機制使得代碼具有更高的靈活性和可擴展性。Python通過幾種內置函數提供了反射的功能&#xff0c;主要包…

機器學習中類別不平衡問題的解決方案

類別不平衡問題 解決方案簡單方法收集數據調整權重閾值移動 數據層面欠采樣過采樣采樣方法的優劣 算法層面代價敏感集成學習&#xff1a;EasyEnsemble 總結 類別不平衡&#xff08;class-imbalance&#xff09;就是指分類任務中不同類別的訓練樣例數目差別很大的情況 解決方案…

智能分析網關V4電瓶車檢測與煙火算法,全面提升小區消防安全水平

2024年2月23日&#xff0c;南京市某小區因電瓶車停放處起火引發火災事故&#xff0c;造成巨大人員傷亡和損失。根據國家消防救援局的統計&#xff0c;2023年全國共接報電動自行車火災2.1萬起。電瓶車火災事故頻發&#xff0c;這不得不引起我們的重視和思考&#xff0c;尤其是在…

阿里云A10推理qwen

硬件配置 vCPU&#xff1a;32核 內存&#xff1a;188 GiB 寬帶&#xff1a;5 Mbps GPU&#xff1a;NVIDIA A10 24Gcuda 安裝 wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda-repo-rhel7-12-1-local-12.1.0_530.30.02-1.x86_64.rpm s…

ZDH-大數據采集-支持KETTLE任務

目錄 項目源碼 預覽地址 支持KETTLE介紹 新增KETTLE任務 配置調度KETTLE 重要說明 感謝支持 項目源碼 zdh_web:GitHub - zhaoyachao/zdh_web: 大數據采集,抽取平臺 預覽地址 后臺管理-登陸 用戶名&#xff1a;zyc 密碼&#xff1a;123456 支持KETTLE介紹 當前平臺不…