qsort函數使用方法總結(詳細全面+代碼)

@[toc]算法

qsort函數原型

void qsort(
    void *base,
    size_t nmemb,
    size_t size,
    int (*compar)(const void *, const void *)
    );

  頭文件:<stdlib.h>
  函數功能:qsort()函數的功能是對數組進行排序,數組有nmemb個元素,每一個元素大小爲size。數組

  參數base - base指向數組的起始地址,一般該位置傳入的是一個數組名
  參數nmemb - nmemb表示該數組的元素個數
  參數size - size表示該數組中每一個元素的大小(字節數)
  參數(*compar)(const void *, const void *) - 此爲指向比較函數的函數指針,決定了排序的順序。
  函數返回值:無
  注意:若是兩個元素的值是相同的,那麼它們的先後順序是不肯定的。也就是說qsort()是一個不穩定的排序算法。函數

compar參數

  compar參數是qsort函數排序的核心內容,它指向一個比較兩個元素的函數,注意兩個形參必須是const void *型,同時在調用compar 函數(compar實質爲函數指針,這裏稱它所指向的函數也爲compar)時,傳入的實參也必須轉換成const void *型。在compar函數內部會將const void *型轉換成實際類型,見下文。ui

int compar(const void *p1, const void *p2);

  若是compar返回值小於0(< 0),那麼p1所指向元素會被排在p2所指向元素的前面
  若是compar返回值等於0(= 0),那麼p1所指向元素與p2所指向元素的順序不肯定
  若是compar返回值大於0(> 0),那麼p1所指向元素會被排在p2所指向元素的後面
  所以,若是想讓qsort()進行從小到大(升序)排序,那麼一個通用的compar函數能夠寫成這樣:指針

int compare (const void * a, const void * b)
 {
   if ( *(MyType*)a <  *(MyType*)b ) return -1;
   if ( *(MyType*)a == *(MyType*)b ) return 0;
   if ( *(MyType*)a >  *(MyType*)b ) return 1;
 }

  注意:你要將MyType換成實際數組元素的類型。
  或者code

//升序排序
 int compare (const void * a, const void * b)
 {
     return ( *(int*)a - *(int*)b );
 }
//降序排列
 int compare (const void * a, const void * b)
 {
     return ( *(int*)b - *(int*)a );
 }

int 數組排序

/* qsort example */
#include <stdio.h>     
#include <stdlib.h>     

int values[] = { 40, 10, 100, 90, 20, 25 };

int compare (const void * a, const void * b)
{
  return ( *(int*)a - *(int*)b );
}

int main ()
{
  int n;
  qsort (values, sizeof(values)/sizeof(values[0]), sizeof(int), compare);
  for (n=0; n<sizeof(values)/sizeof(values[0]); n++)
     printf ("%d ",values[n]);
  return 0;
}

結構體排序

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include<stdlib.h>
// void qsort(void* base, size_t num, size_t size, int(*compare)(const void*, const void*))

typedef struct
{
    char name[30];   // 學生姓名
    int Chinese;    // 語文成績
    int Math;        // 數學成績  
    int English;     // 英語成績
}st; 
int cmp(const void* a, const void* b)
{
    st* pa = (st*)a;
    st* pb = (st*)b;
    int num1 = pa->Chinese + pa->English + pa->Math;
    int num2 = pb->Chinese + pb->English + pb->Math;

    //return (int)num1 - num2;   // 從小到大,
    return (int)num2 - num1;   //  從大到小
}
int main(void)
{
    st students[7] = {
        {"周",97,68,45},
        {"吳",100,32,88},
        {"鄭",78,88,78},
        {"王",87,90,89},
        {"趙",87,77,66},
        {"錢",59,68,98},
        {"孫",62,73,89}
    };
    qsort(students, 7, sizeof(st), cmp);   // 注意區別 students 與 st

    for (int i = 0; i < 7; i++)
    {
        printf("%s%4d%4d%4d\t", students[i].name, students[i].Chinese, students[i].Math, students[i].English);
        printf("總分:%d\n", students[i].Chinese + students[i].English + students[i].Math);
    }

    system("pause");
    return 0;
}

字符串指針數組排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int compare(const void *arg1, const void *arg2);

int
main(int argc, char** argv)
{
    int i;

    char *arr[5] = { "i", "love", "c", "programming", "language" };

    qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(char *), compare);

    for (i = 0; i < 5; i++) {
        printf("%s ", arr[i]);
    }
    printf("\n");
   
}

int compare(const void *arg1, const void *arg2) {
    char *a = *(char**)arg1;
    char *b = *(char**)arg2;
    int result = strcmp(a, b);
    if (result > 0) {
        return 1;
    }
    else if (result < 0) {
        return -1;
    }
    else {
        return 0;
    }
}

  那麼咱們向qsort傳入arr以後,qsort將arr理解爲指向數組中第一個元素的指針,因此形參表中,arg1和arg2實際上是指向「指向常量字符串的指針」的指針,是char**。而咱們須要傳給strcmp這個字符串比較函數的,是「指向字符串的指針」,是char*,因此咱們將void*轉換爲char**,而後解引用,獲得char*,賦予a和b。接下來使用strcmp對a和b進行比較。(數組名自己算一層指針,而裏面的內容又是一層指針,數組存放的是指向字符串的地址)排序

字符串二維數組排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int compare(const void *arg1, const void *arg2);

int
main(int argc, char** argv)
{
    int i;

    char arr[5][16] = { "i", "love", "c", "programming", "language" };

    qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);
    printf("%s\n", arr[0]);
    for (i = 0; i < 5; i++) {
        printf("%s ", arr[i]);
    }
    printf("\n");
}

int compare(const void *arg1, const void *arg2) {
    char *a = (char*)arg1;
    char *b = (char*)arg2;
    int result = strcmp(a, b);
    if (result > 0) {
        return 1;
    }
    else if (result < 0) {
        return -1;
    }
    else {
        return 0;
    }
}

  這裏對二維數組進行排序,實際上是對二維數組的第二維中存放的字符串進行排序。因此qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), compare);對qsort函數的調用中,第二個參數是待排元素的個數(5個),第三個參數是待排元素的大小(16)。字符串

  咱們將arr傳入qsort函數,qsort函數將arr理解爲指向數組第一個元素的指針,arr的第一個元素是arr[0][0],因此參數arg1和arg2指的是指向"a[i][0]"的指針,咱們知道,a[i][0]是字符,就是char,因此arg1和arg2指的是char *。咱們將void*轉換爲char*,賦予a和b,調用strcmp函數對a和b進行比較。原型

整型二維數組(力扣題目)

  1. 最接近原點的 K 個點

  咱們有一個由平面上的點組成的列表 points。須要從中找出 K 個距離原點 (0, 0) 最近的點。(這裏,平面上兩點之間的距離是歐幾里德距離。)你能夠按任何順序返回答案。除了點座標的順序以外,答案確保是惟一的。數學

示例 1:

輸入:points = [[1,3],[-2,2]], K = 1
輸出:[[-2,2]]
解釋: (1, 3) 和原點之間的距離爲sqrt(10), (-2, 2) 和原點之間的距離爲 sqrt(8), 因爲 sqrt(8) < sqrt(10),(-2, 2) 離原點更近。 咱們只須要距離原點最近的 K = 1 個點,因此答案就是 [[-2,2]]。
示例 2:
輸入:points = [[3,3],[5,-1],[-2,4]], K = 2
輸出:[[3,3],[-2,4]] (答案 [[-2,4],[3,3]] 也會被接受。)
提示:
1 <= K <= points.length <= 10000
-10000 < pointsi < 10000
-10000 < pointsi < 10000

/* qsort排序二維數組,cmp的每一個元素都是一個獨立的 int 數組,也就是指針 */
int cmp(const void* a, const void* b) {

    // 轉換爲對應一維數組
    int* arry1 = *(int**)a;
    int* arry2 = *(int**)b;
    
    // 獲取對應arry1 的兩個元素
    int x1 = *arry1;
    int y1 = *(arry1 + 1);

    int x2 = *arry2;
    int y2 = *(arry2+1);

    return (x1*x1 + y1*y1) - (x2*x2 + y2*y2);
}


int** kClosest(int** points, int pointsSize, int* pointsColSize, int K, int* returnSize, int** returnColumnSizes){
    if(points==NULL || pointsSize==0 || K==0) return NULL;
    
    qsort(points, pointsSize, sizeof(int)*pointsColSize[0], cmp);
    /*   這裏注意 qsort 的傳參,使用不當會報錯
    Line 11: Char 11: runtime error: load of misaligned address 0x602000000032 for type 'int *', which requires 8 byte alignment (solution.c)       0x602000000032: note: pointer points here
    */

    // 指定return輸出的二維數組是包含有幾個一維數組
    *returnSize = pointsSize > K ? K : pointsSize;
    
    *returnColumnSizes = (int*)malloc(sizeof(int*)*(*returnSize));
    // 指定每一個一維數組的 col 
    for(int i = 0; i< (*returnSize); i++) {
        (*returnColumnSizes)[i] = 2;
    }
    return points;
}

如遇到排版錯亂的問題,能夠經過如下連接訪問個人CSDN。

**CSDN:[CSDN搜索「嵌入式與Linux那些事」]

相關文章
相關標籤/搜索