網站首頁 編程語言 正文
前言
這篇文章就是指針進階的收尾環節了,相信看過C語言進階——指針(下)的小伙伴一定還記著文章末尾的回調函數吧。這篇文章就是借qsort函數的模擬實現來給小伙伴們展示一下回調函數的運用。
1.冒泡排序的實現
在實現qsort函數,相信有的小伙伴對冒泡排序還存有疑惑,甚至是第一次接觸這個名詞,那么我們就先來講講冒泡排序。
1.1冒泡排序的概念
“冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果順序(如從大到小、首字母從Z到A)錯誤就把他們交換過來。走訪元素的工作是重復地進行,直到沒有相鄰元素需要交換,也就是說該元素列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名“冒泡排序”。
相信聰明的你已經知道了冒泡排序是一種依次比較相鄰元素并按照相應規則進行排序的排序方法。
在這種排序過程中,重要的元素共有兩個,分別是冒泡排序的趟數以及比較的次數。一般而言,趟數是元素的個數減一得到,為什么不等于元素的個數呢?因為每進行一趟冒泡排序,就會有一個元素來到它正確的位置,所以當除了最后一個元素以外的其他元素都來到了正確位置的時候,那么最后一個元素也一定處于正確位置。
說完趟數,再來聊聊比較次數。有親自實踐的小伙伴們一定發現了在進行第一趟冒泡排序的時候,比較的次數是最多的,是除了第一個元素以外的所有元素都要與之比較,也就是元素的個數減一,但是隨著趟數的增加,比較的次數也會隨之減少,究其原因,是因為每經過一次冒泡排序,就會有一個元素來到正確的位置,那么這個正確的元素也就無需參加后續的比較了。
那么具體的代碼實現究竟是怎么樣呢?接下來就讓我們一起揭開它神秘的面紗,一探究竟!
1.2具體代碼的實現
void bubble_sort(int arr[], int sz)
{
//趟數
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//一趟冒泡排序的過程
int j = 0;
for (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;
}
}
}
}
2.qsort函數
在了解完冒泡排序之后,有的小伙伴還是第一次見到qsort函數,那么下面我們就來簡單介紹一下qsort函數。
首先我們要清楚的是qsort函數是庫里面的函數,所以我們在使用的時候要引用頭文件<stdlib.h>。
然后我們再來了解一下這個函數的各個部分。第一個是返回類型,從上圖中我們可以看到返回類型是void,也就是說當我們在引用這個函數的時候,它并不會返回任何參數。第二個是參數部分,第一個參數是一個指針變量,第二、三個參數是無符號的整型變量,第四個就是我們之前講解過的函數指針變量。在第四個參數部分也就體現了回調函數這一功能。
最后我們來講講這個函數該怎么使用。在引用完頭文件后,我們下一步就是要對這個函數進行傳參,在意義上分別是要排序的對象,元素個數,元素大小(以字節為單位),判斷是否交換的函數(根據需求自寫)。
說到第四個參數所指向的函數需要根據需求自己來寫,可能有小伙伴就疑惑了,到底要怎么寫呢。別怕,上面這幅圖片可以說是為我們函數的書寫提供了方向。首先你要確保你書寫的函數的返回類型為int,并且依據交換的原則來進行返回值的代碼書寫。拿整型數組排序為例,如果你想要最終數組的整形呈現升序排序,那么如果兩個數是降序排序就應該返回小于0的整型。具體代碼的實現如下,以整形數組和結構體為例。
//用qsort函數實現各種類型的排序
//整形數組的排序
int cmp_int(void const* e1, void const* e2)
{
return *(int*)e1 - *(int*)e2;
}
int main()
{
int i = 0;
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, 4, cmp_int);
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
//結構體的排序
struct stu
{
char name[20];
int age;
};
int cmp_age(void const*e1, void const*e2)
{
return (((struct stu*)e1)->age - ((struct stu*)e2)->age);
}
int cmp_name(void const* e1, void const* e2)
{
return strcmp(((struct stu*)e1)->name ,((struct stu*)e2)->name);
}
int main()
{
struct stu Stu[3] = { {"zhangsan", 20},{"wangwu", 42},{"lisi",29}};
int sz = sizeof(Stu) / sizeof(Stu[0]);
//qsort(Stu, sz, sizeof(Stu[0]), cmp_age);
qsort(Stu, sz, sizeof(Stu[0]), cmp_name);
return 0;
}
3.qsort函數的實現
隨著我們學習的不斷深入,類型的不斷豐富,我們會發現上面的冒泡排序已然滿足不了我們的需求,諸如結構體的排序,這種代碼已經是無能為力了。那么接下來我們就自己來利用冒泡排序的原理來書寫qsort函數。
//實現元素的交換
void swap(char* e1, char* e2, size_t sz)
{
size_t i = 0;
for (i = 0; i < sz; i++)
{
char tmp = 0;
tmp = *e1;
*e1 = *e2;
*e2 = tmp;
e1++;
e2++;
}
}
//qsort函數的自定義
void bubble_sort(void* base, size_t num, size_t size, int (*compar)(const void*e1, const void*e2))
{
size_t i = 0;
size_t j = 0;
//冒泡排序的趟數
for (i = 0; i < num-1; i++)
{
//比較的次數
for (j = 0; j < num - i - 1; j++)
{
if (compar((char *)base+j*size,(char*)base+(j+1)*size)>0)
{
//交換
swap((char*)base + j*size, (char*)base + (j + 1)*size, size);
}
}
}
}
原文鏈接:https://blog.csdn.net/m0_73953114/article/details/128766018
相關推薦
- 2022-03-19 C語言數據結構之隊列算法詳解_C 語言
- 2022-04-04 react 報錯Assign arrow function to a variable before
- 2022-11-04 LyScript實現Hook改寫MessageBox的方法詳解_python
- 2022-09-26 GO語言基本類型String和Slice,Map操作詳解_Golang
- 2022-10-19 python基礎教程之csv文件的寫入與讀取_python
- 2022-05-25 python?序列去重并保持原始順序操作_python
- 2022-09-20 linux系統下用.sh文件執行python命令的方法_linux shell
- 2023-01-05 淺析C++中的重載,隱藏和覆蓋_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支