最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于C語言qsort函數(shù)詳解

 更新時間:2021年09月03日 15:00:23   作者:芒果再努力  
這篇文章主要介紹了關(guān)于C語言qsort函數(shù)詳解的相關(guān)資料,需要的朋友可以參考下面文章內(nèi)容

C語言qsort函數(shù)詳解

一.qsort函數(shù)是什么

我們可以使用  搜索庫函數(shù)網(wǎng)址或者MSDN軟件進行查找。

qsort()函數(shù):快速排序的函數(shù)  -引用stdlib.h頭文件

參數(shù)說明:

void qsort ( 

    void* base, //要排序的目標數(shù)組
    size_t num,     //待排序的元素個數(shù)
    size_t width,    //一個元素的大小,單位是字節(jié)
    int(*cmp)(const void* e1, const void* e2)

);    

其中cmp是函數(shù)指針,cmp指向的是:排序時,用來比較兩個元素的函數(shù)。需要自己編寫。

返回值:

       

 二.使用qsort排序-以升序為例

關(guān)于void*型指針:

void*:無具體類型的指針   能夠接收任意類型的地址
 缺點:不能進行運算。不能+-整數(shù),不能解引用

int a  = 0;
float f = 5.5f;
void* p1 = &a;
void* p2 = &f;
p1 = p1+1;    //err

1.整形數(shù)組排序

注意:

(1).比較函數(shù)的參數(shù)類型為void* ,我們要進行強制類型轉(zhuǎn)換!且要解引用才能得到對應(yīng)的值!

(2).若我們想排成降序,只需要寫成e2-e1即可

void Print(int* arr, int sz)
{
 int i = 0;
 for (i = 0; i < sz; i++)
 {
  printf("%d ", *(arr + i));
 }
 printf("\n");
}
//比較整形
//注意類型時void* 所以要強制類型轉(zhuǎn)化,還要解引用才是對應(yīng)的值?。。?
int cmp_int(const void* e1, const void* e2)
{
 return *(int*)e1 - *(int*)e2;
}
void test1()
{
 int arr[] = { 9,8,7,6,7,5,4,8 };
 int sz = sizeof(arr) / sizeof(arr[0]);
 qsort(arr, sz, sizeof(arr[0]), cmp_int);
 Print(arr, sz);
}

2.字符數(shù)組排序

注意使用sizeof()操作符strlen()函數(shù)的區(qū)別

//注意要要強制類型轉(zhuǎn)換?。?要解引用?。?!  本質(zhì)上是比較Ascii值
int cmp_char(const void* e1, const void* e2)
{
    return *(char*)e1 - *(char*)e2;
}
void test4()
{
 char arr[] ="mango";
    //若使用sizeof計算長度:
 //int sz = sizeof(arr) / sizeof(arr[0]); //6
 //qsort(arr, sz-1, sizeof(arr[0]), cmp_float);
    //因為sizeof把\0也算進去了,所以計算出來的值比字符串本身長度多1
    
    int sz = strlen(arr); //5
    qsort(arr, sz, sizeof(arr[0]), cmp_char);
 printf("%s\n",arr);
}

3.字符指針數(shù)組排序

先看看下面這段程序有沒有問題?

int cmp_chars(const void* e1, const void* e2)
{
 return strcmp((char*)e1, *(char*)e2);
}
void test2()
{
  char* arr1 = "abc";
  char* arr2 = "wcad";
  char* arr3 = "cab";
  char* p[3] = { arr1,arr2,arr3 };
 int sz = sizeof(p) / sizeof(p[0]);
 qsort(p, sz, sizeof(p[0]), cmp_chars);
 int i = 0;
 for (i = 0; i < sz; i++)
 {
  printf("%s\n", p[i]);
 }
}
 

打印出來發(fā)現(xiàn):結(jié)果是錯誤的!

 ->調(diào)試后發(fā)現(xiàn):e2存放的是p的地址(char**類型),e1存放的是p指向的下一個元素的地址(char**類型)       

對于這種寫法,傳進去的是p的地址,strcmp()會將p地址對應(yīng)的內(nèi)容轉(zhuǎn)化成字符串,也就是將p中arr1,arr2,arr3的地址轉(zhuǎn)化成字符串

實際上應(yīng)該傳p地址空間中arr1,arr2的地址,這樣strcmp()才能找到arr1和arr2對應(yīng)的字符串,因此得先把e1,e2轉(zhuǎn)化成char**,這樣解引用以后才是一個char*的地址

原因:把p傳給qsort,p是數(shù)組名->首元素地址,元素類型為char*>,所以p的類型為:char**類型。  所以e1 和e2也要強制類型轉(zhuǎn)化為char**,解引用e1,e2才是對應(yīng)字符串的地址!

正解:

int cmp_chars(const void* e1, const void* e2)
{
 return strcmp(*(char**)e1, *(char**)e2);
}
void test2()
{
  char* arr1 = "abc";
  char* arr2 = "wcad";
  char* arr3 = "cab";
  char* p[3] = { arr1,arr2,arr3 };
 int sz = sizeof(p) / sizeof(p[0]);
 qsort(p, sz, sizeof(p[0]), cmp_chars);
 int i = 0;
 for (i = 0; i < sz; i++)
 {
  printf("%s\n", p[i]);
 }

4.結(jié)構(gòu)體數(shù)組排序

比較年齡->實際比較的是整形

比較名字->實際比較的是字符串->使用strcmp函數(shù),不能使用 == 判斷

struct Stu
{
 int age;
 char name[20];
};
//比較結(jié)構(gòu)體中元素的年齡
int cmp_age(const void* e1, const void* e2)
{
 //本質(zhì)是比較整形
 return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//比較名字
int cmp_name(const void* e1, const void* e2)
{
 //本質(zhì)是字符串比較->使用strcmp函數(shù)
 return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
void test2()
{
 //創(chuàng)建結(jié)構(gòu)體數(shù)組,用大括號初始化
 struct Stu s[3] = { {19,"Mango"},{18,"Lemon"},{20,"Hello"} };
 int sz = sizeof(s) / sizeof(s[0]);
 //以年齡排
 qsort(s, sz, sizeof(s[0]), cmp_age);
 printf("%s %d ",s[0].name,s[0].age);
 printf("%s %d ", s[1].name, s[1].age);
 printf("%s %d ", s[2].name, s[2].age);
 printf("\n");
 //以姓名排
 qsort(s, sz, sizeof(s[0]), cmp_name);
 printf("%s %d ", s[0].name, s[0].age);
 printf("%s %d ", s[1].name, s[1].age);
 printf("%s %d ", s[2].name, s[2].age);
 printf("\n");
}

5.浮點型數(shù)組排序

注意:比較函數(shù)中,返回類型是int,最后相減的值要強制類型轉(zhuǎn)化為int ,但這也會造成錯誤,建議使用方法2.

寫法1:可能會出錯

// 原因: 0.2 -0.1 = 0.1 強制類型轉(zhuǎn)化為int后 結(jié)果為0
//int cmp_float(const void* e1, const void* e2)
//{
// //返回類型是int  所以相減后的結(jié)果要強制類型轉(zhuǎn)化
// return (int)(*(float*)e1 - *(float*)e2);
//}
 


寫法2:對應(yīng)上qsort的返回值

int cmp_float(const void* e1, const void* e2)
{
 if ((*(float*)e1 - *(float*)e2) > 0.00000)
  return 1;
 else if ((*(float*)e1 - *(float*)e2) == 0.000000)
  return 0;
 else
  return -1;
}
void test3()
{
 float arr[5] = { 5.01f,5.01f,0.02f,0.01f,5.001f };
 int sz = sizeof(arr) / sizeof(arr[0]);
 qsort(arr, sz, sizeof(arr[0]), cmp_float);
 int i = 0;
 for (i = 0; i < sz; i++)
 {
  printf("%f ", arr[i]);
 }
}

三.使用冒泡排序思想模擬實現(xiàn)qsort函數(shù)

1.什么是冒泡排序

主要思想:相鄰的兩個元素進行比較

 

 對于冒泡排序: n個元素 共進行n-1趟冒泡排序。一趟可以使一個元素在特定位置上,每趟排序可以少比較一個元素

但是冒泡排序只能排序整形

 2.冒泡排序代碼

void BubbleSort(int* arr, int sz)
{
 int i = 0;
 int j = 0;
 //共進行sz-1趟
 for (i = 0; i < sz-1; i++)
 {
  int flag = 1;//每一趟進來都假設(shè)有序
        // 每一趟
  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;
    flag = 0;
   }
  }
        //若falg還是1,說明沒有交換->已經(jīng)有序了break退出
  if (flag == 1)
  {
   break;
  }
 }
}
int main()
{
 int arr[10] = { 2,3,6,7,9,0,0,3,2,10 };
 int sz = sizeof(arr) / sizeof(arr[0]);
 BubbleSort(arr, sz);
 return 0;
}

3. 使用冒泡排序思想模擬實現(xiàn)qsort函數(shù)

qsort庫函數(shù)使用的是什么參數(shù),我們設(shè)計的函數(shù)就使用什么參數(shù)!

 

(1)為何將base強制類型轉(zhuǎn)化為char*型指針:

原因:char* 指針+1跳過一個字節(jié),+width:跳過width個字節(jié),指向下一個元素。轉(zhuǎn)化為其他類型不合適

(2)交換函數(shù):還要把寬度(每個元素所占字節(jié)數(shù))傳過去

因為交換的時候是傳地址,所以要知道元素的寬度,一個字節(jié)一個字節(jié)的交換 ,這樣也證明了使用char*指針的好處!

(3)char*)base + j * width, (char*)base + (j + 1) * width,

  當j = 0時:比較的是第一個元素和第二個元素
   j = 1時,比較的是第二個元素和第三個元素
    ....  很妙的寫法

//交換 --一個字節(jié)一個字節(jié)的交換,共交換width次
void Swap(char* buf1, char* buf2, size_t width)
{
 size_t i = 0;
 for (i = 0; i < width; i++)
 {
  char tmp = *buf1;
  *buf1 = *buf2;
  *buf2 = tmp;
  buf1++;
  buf2++;
 }
}
void my_BubbleSort(void* base, size_t num,size_t width, int(*cmp)(const void* e1, const void* e2))
{
 //冒泡排序
 //若要排序n個元素,只需要進行n-1趟
 //每一趟可以少比較一個元素,每一趟可以使一個元素在確定的位置上
 //num:要排序元素的個數(shù) 類型是size_t 
    //num是無符號數(shù) 防止產(chǎn)生警告 所以i和j也定義為size_t
    // size_t == unsigned int 
 size_t i = 0;
 size_t j = 0;
 
 //共進行num-1趟
 for (i = 0; i < num; i++)
 {
  //每一趟
  for (j = 0; j < num - 1 - i; j++)
  {
   //比較
   //傳地址   
   //相鄰兩個元素比較   width:寬度,每個元素所占字節(jié)
   //排成升序
   if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
   {
    //交換兩數(shù)
    Swap( (char*)base + j * width, (char*)base + (j + 1) * width, width );
   }
  }
 }
}

當然 ,交換也可以使用庫函數(shù)memcpy

 

dest:目標空間

 src:要拷貝到目標空間的字符 -因為不作修改,所以可以用const修飾

count:字節(jié)數(shù)

char tmp [30];    //防止結(jié)構(gòu)體類型之類的類型    臨時空間
memcpy(tmp, (char*)base + j * size, size); 
memcpy( (char*)base + j * size,  (char*)base + (j + 1) * size, size);
memcpy( (char*)base + (j + 1) * size, tmp, size);

以上就是關(guān)于C語言qsort函數(shù)詳解的詳細內(nèi)容,更多關(guān)于C語言qsort函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++類成員函數(shù)如何做函數(shù)參數(shù)

    c++類成員函數(shù)如何做函數(shù)參數(shù)

    這篇文章主要介紹了c++類成員函數(shù)如何做函數(shù)參數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語言實現(xiàn)簡單通訊錄功能

    C語言實現(xiàn)簡單通訊錄功能

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單通訊錄功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++控制臺繪圖頭文件實例代碼

    C++控制臺繪圖頭文件實例代碼

    控制臺(console)是電腦的最基本交互接口,通常包括鍵盤(keyboard)和屏幕(screen),下面這篇文章主要給大家介紹了關(guān)于C++控制臺繪圖頭文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-01-01
  • 基于c++的中國象棋游戲設(shè)計與實現(xiàn)

    基于c++的中國象棋游戲設(shè)計與實現(xiàn)

    這篇文章主要介紹了基于c++的中國象棋游戲設(shè)計與實現(xiàn),主要操作是possibleMove(int?x,?int?y),通過整個棋盤每個位置上的信息、中國象棋的規(guī)則來獲得位置(x,?y)這個棋子可以移動到的位置,需要的朋友可以參考一下
    2022-02-02
  • EasyX實現(xiàn)自由落體小球

    EasyX實現(xiàn)自由落體小球

    這篇文章主要為大家詳細介紹了EasyX實現(xiàn)自由落體小球,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Qt中QUndoView控件的具體使用

    Qt中QUndoView控件的具體使用

    QUndoView是Qt框架中用于可視化顯示QUndoStack內(nèi)容的控件,本文主要介紹了Qt中QUndoView控件的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • Qt調(diào)用MATLAB引擎混合編程的過程詳解

    Qt調(diào)用MATLAB引擎混合編程的過程詳解

    這篇文章給大家介紹了Qt調(diào)用MATLAB引擎混合編程的全過程,文中通過圖文結(jié)合的方式給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • C++實現(xiàn)藍橋杯競賽題目---搭積木

    C++實現(xiàn)藍橋杯競賽題目---搭積木

    這篇文章主要介紹了C++實現(xiàn)藍橋杯競賽題目---搭積木,本篇文章通過題目分析列舉公式進行分析算法,包含詳細的圖文,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言實現(xiàn)數(shù)組的循環(huán)左移,右移,翻轉(zhuǎn)的示例

    C語言實現(xiàn)數(shù)組的循環(huán)左移,右移,翻轉(zhuǎn)的示例

    今天小編就為大家分享一篇C語言實現(xiàn)數(shù)組的循環(huán)左移,右移,翻轉(zhuǎn)的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • C語言實現(xiàn)簡易文本編輯器

    C語言實現(xiàn)簡易文本編輯器

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡易文本編輯器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05

最新評論

金阳县| 玉山县| 新竹市| 潼南县| 青铜峡市| 汉中市| 出国| 安塞县| 墨竹工卡县| 南康市| 青龙| 涟水县| 赣榆县| 青海省| 惠水县| 阿克陶县| 土默特右旗| 剑阁县| 龙海市| 昌江| 观塘区| 嵩明县| 大宁县| 南和县| 栾川县| 绥阳县| 普陀区| 宁都县| 虞城县| 榆社县| 荣昌县| 乐至县| 吕梁市| 宝应县| 广宗县| 长垣县| 栖霞市| 丹寨县| 宽甸| 汉阴县| 庆阳市|