怎么建立自己的站點(diǎn)上海網(wǎng)站建設(shè)開(kāi)發(fā)
文章目錄
- 🚀前言
- 🚀void*類型指針
- 🚀庫(kù)函數(shù)qsort的使用
- 🚀利用冒泡排序?qū)崿F(xiàn)庫(kù)函數(shù)qsort()
🚀前言
今天阿輝將為大家介紹庫(kù)函數(shù)qsort的使用,還包括利用冒泡排序模擬實(shí)現(xiàn)qsort以及void*
類型的指針,關(guān)注阿輝不迷路哦 😘 ,內(nèi)容干貨滿滿😋,接下來(lái)就跟著阿輝一起學(xué)習(xí)吧👊
🚀void*類型指針
鐵子們都知道一種指針只能接收同類型的地址,否則編譯器就會(huì)報(bào)錯(cuò),那有沒(méi)有可以接收任意類型地址的指針呢?答案是有的,就是void*
類型的指針
例如:
int a = 10;
char c = 'c';
float f = 1.2f;
void*p = NULL;
p = &a;
p = &c;
p = &f;
void*
類型指針可以接受任何類型的變量的地址,它就像一個(gè)“垃圾桶”一樣,任何的地址都可以往里面“扔”,所以他也被稱為泛型指針,但是void*
類型的指針也有它的局限性,因?yàn)?code>void*無(wú)具體類型,SOvoid*
類型的指針無(wú)法進(jìn)行指針運(yùn)算也無(wú)法進(jìn)行解引用操作
既然如此,那void*
類型的指針有何應(yīng)用場(chǎng)景,鐵子們別急我們接著看👇
🚀庫(kù)函數(shù)qsort的使用
鐵子們,咱們今天的重點(diǎn)來(lái)了,qsort()
是C語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供的專門用來(lái)給數(shù)組排序的一個(gè)庫(kù)函數(shù)
qsort()函數(shù)的聲明
void qsort(void* base, size_t num, size_t size, int (*compar)(const void* p1, const void* p2));庫(kù)函數(shù)qsort()有四個(gè)參數(shù), 不返回
void* base 這個(gè)參數(shù)是指向數(shù)組首元素的指針
size_t num這個(gè)參數(shù)指的是數(shù)組中的元素個(gè)數(shù)
size_t size這個(gè)參數(shù)是數(shù)組中每個(gè)元素的大小,以字節(jié)為單位
對(duì)于庫(kù)函數(shù)qsort()
的第四個(gè)參數(shù)int (*compar)(const void* ,const void*)
,是一個(gè)函數(shù)指針,要使用qsort()
得我們自己定義一個(gè)返回值為int
類型有兩個(gè)const
修飾的void*
類型的指針的參數(shù),并且返回值遵循如下規(guī)則的函數(shù):
返回值< 0 第一個(gè)參數(shù)應(yīng)在第二個(gè)參數(shù)前,無(wú)需交換
返回值> 0 第二個(gè)參數(shù)應(yīng)在第一個(gè)參數(shù)前,需要交換
返回值= 0 誰(shuí)在前無(wú)所謂,無(wú)去交換
qsort()
函數(shù)最厲害的就是它可以給任何數(shù)據(jù)排序,并且可以根據(jù)我們提供的比較函數(shù)實(shí)現(xiàn)升序或是降序,鐵子們,我們來(lái)看看qsort()
是如何使用的👇
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct Stu
{int age;//年齡char name[20];//名字
};
//以結(jié)構(gòu)體Stu成員age的數(shù)字大小排升序
int StuAgecomp(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}
//以結(jié)構(gòu)體Stu成員name利用庫(kù)函數(shù)strcmp()給字符串排序
int StuNamecomp(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
//打印函數(shù),打印排序后內(nèi)容
void print(struct Stu arr[],int size)
{for (int i = 0; i < size; i++){printf("%d %s ", arr[i].age, arr[i].name);}printf("\n");
}int main()
{struct Stu arr[] = { {19,"tangminghui"},{12,"tanzihao"},{30,"zenghongsen"} };int size = sizeof(arr[0]);//數(shù)組每個(gè)元素的大小,單位字節(jié)int num = sizeof(arr) / size;//數(shù)組的元素個(gè)數(shù)qsort(arr, num, size, StuAgecomp);print(arr,num);qsort(arr, num, size, StuNamecomp);print(arr,num);return 0;
}
輸出:
🚀利用冒泡排序?qū)崿F(xiàn)庫(kù)函數(shù)qsort()
相信鐵子們對(duì)冒泡排序并不感冒,庫(kù)函數(shù)qsort()
的內(nèi)核其實(shí)就是快排不過(guò)阿輝實(shí)力有限暫時(shí)還不會(huì) 😭,這里阿輝利用冒泡函數(shù)給大家徒手干一個(gè)
函數(shù)名就叫UpgradeBubbleSort
升級(jí)版冒泡排序 😜(以下簡(jiǎn)稱冒泡函數(shù))
我們的冒泡函數(shù)的參數(shù)與庫(kù)函數(shù)qsort
一樣,排序就是冒泡排序的皮,主要的問(wèn)題是泛型參數(shù)如何交換,這里我們定義一個(gè)交換函數(shù)swp
來(lái)實(shí)現(xiàn)
下面是冒泡函數(shù)的具體實(shí)現(xiàn),代碼以及詳解注釋:
void UpgradeBubbleSort(void* base, size_t num, size_t size, int (*cmp)(const void* p1, const void* p2))
{for (int i = 0; i < num - 1; i++){int flag = 0;//記錄一趟下來(lái)是否發(fā)生交換for (int j = 0; j < num - i - 1; j++){//數(shù)據(jù)的大小這時(shí)就有用了,找到后一個(gè)數(shù)據(jù)的起始地址char* p = (char*)base + j * size;//利用一個(gè)變量簡(jiǎn)化代碼//像下面注釋這么寫太挫了//if (cmp((char*)base + j * size, (char*)base + (j + 1) * size))//冒泡排序的思想嘛,前一個(gè)數(shù)據(jù)和后一個(gè)比if (cmp(p, p + size) > 0){swp(p, size);flag = 1;}}if (flag == 0)//沒(méi)有交換說(shuō)明已有序無(wú)須繼續(xù),跳出循環(huán){break;}}
}
為什么要把void*
指針強(qiáng)制轉(zhuǎn)化為char*
類型,第一點(diǎn),因?yàn)榉奖愀鶕?jù)數(shù)據(jù)大小找到數(shù)據(jù),char*
加減整數(shù)跳過(guò)該整數(shù)倍數(shù)的字節(jié)空間和數(shù)據(jù)大小size
結(jié)合使用,就能找到數(shù)據(jù)中每個(gè)元素;第二點(diǎn),因?yàn)榻粨Q數(shù)據(jù)時(shí)把對(duì)應(yīng)位置上的一個(gè)字節(jié)大小空間中的內(nèi)容交換,即可交換兩個(gè)數(shù)據(jù)的內(nèi)容
給鐵子們上圖:
swp
函數(shù)的具體實(shí)現(xiàn),代碼以及詳解注釋:
//交換函數(shù)
void swp(char* p, int sz)
{//有幾個(gè)字節(jié)交換幾次//p+sz表示下一個(gè)數(shù)據(jù)for (int i = 0; i < sz; i++){//倆個(gè)數(shù)據(jù)對(duì)應(yīng)位置的字節(jié)交換位置,完成交換char tmp = *(p + i);*(p + i) = *(p + sz + i);*(p + sz + i) = tmp;}
}
下面是完整的升級(jí)版冒泡排序函數(shù) 😘
//交換函數(shù)
void swp(char* p, int sz)
{for (int i = 0; i < sz; i++){//倆個(gè)數(shù)據(jù)對(duì)應(yīng)位置的字節(jié)交換位置,完成交換char tmp = *(p + i);*(p + i) = *(p + sz + i);*(p + sz + i) = tmp;}
}//套著標(biāo)準(zhǔn)冒泡排序的皮
void UpgradeBubbleSort(void* base, size_t num, size_t size, int (*cmp)(const void* p1, const void* p2))
{for (int i = 0; i < num - 1; i++){int flag = 0;//記錄一趟下來(lái)是否發(fā)生交換for (int j = 0; j < num - i - 1; j++){char* p = (char*)base + j * size;//利用一個(gè)變量簡(jiǎn)化代碼//像下面注釋這么寫太挫了//if (cmp((char*)base + j * size, (char*)base + (j + 1) * size))if (cmp(p, p + size) > 0){swp(p, size);flag = 1;}}if (flag == 0)//沒(méi)有交換說(shuō)明已有序無(wú)須繼續(xù),跳出循環(huán){break;}}
}
到這里,阿輝今天對(duì)于C語(yǔ)言中庫(kù)函數(shù)qsort()的分享就結(jié)束了,希望這篇博客能讓大家有所收獲, 如果覺(jué)得阿輝寫得不錯(cuò)的話,記得給個(gè)贊唄,你們的支持是我創(chuàng)作的最大動(dòng)力🌹