1. 程式人生 > >C語言排序函式和二分查詢呼叫方法

C語言排序函式和二分查詢呼叫方法

程式設計時經常遇到對陣列排序或在一個數組中查詢數字的情況,C庫<stdio.h>中提供了簡便的呼叫方法,將排序演算法封裝成通用的排序函式;

排序函式qsort

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

在使用時,使用者需要自己編寫一個判斷兩個數(不僅限於數字)比較大小的方法;
比如簡單的判斷兩個數字的大小:

int num_comp(const int *a,const int *b)
{
    if(*a==*b)
        return 0;
    return *a>*b?1:-1;
}

注意函式的格式是不能變的,且第一個引數>第二個引數,需要返回一個正數.
在呼叫時,該如何呼叫呢?
如果有一個數組int num[100];裡面是100個未排序的數字,要將這個陣列按升序排列;
呼叫qsort函式:

qsort(num,100,sizeof(int),(int (*)(const void *,const void *))num_comp);

說明一下這裡的引數,
第一個引數num是陣列名;
第二個引數100是說這個要排序的陣列大小num[0]到num[100-1];
第三個引數是排序的元素大小,這裡是Int型別;
第四個是比較函式的指標,(int (*)(const void *,const void *))

是指標型別轉換;num_comp 是要比較函式的地址;

#include<iostream>
#include<stdlib.h>
#include<ctime>
using namespace std;
int num_comp(const int *a,const int *b);
int main()
{
    int num[100]={0};
    srand(time(0));
//陣列初始化,填滿0-100隨機數;
    for(int i=0;i<100;i++)
        num[i]=rand()%101;
//升序排序;
    qsort(
num,100,sizeof(int),(int (*)(const void *,const void *))num_comp); //輸出; for(int i=0;i<100;i++) cout<<num[i]<<' '; } int num_comp(const int *a,const int *b) { if(*a==*b) return 0; return *a>*b?1:-1; }

如果想要進行降序排列,只需要修改return *a>*b?1:-1;變成return *a<*b?1:-1;即可.

二分查詢

C庫<stdlib.h>中提供了二分查詢函式,用於解決在已排序陣列中尋找一個數字;
其函式原型是:

 void *bsearch( const void *key, const void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) );

引數說明:
1、key是要尋找的關鍵數字,傳入時以地址方式傳入;
2、buf是要尋找的陣列,傳入首地址;
3、num是陣列的元素個數,可以用巨集定義解決;
4、size是陣列元素的大小;
5、比較函式;
呼叫方法:
需要使用者提供一個比較函式,同上面快排的比較函式;

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

#define SIZE(x) sizeof(x)/sizeof(x[0])  //巨集定義陣列元素個數;
typedef int(*COMP_P)(const void *,const void *);    //定義指向比較函式的指標型別;
int num_comp(const int *a,const int *b);
int main()
{
    //隨機初始化陣列;
    int num[100]={0};
    srand(time(0));
    for(int i=0;i<100;i++)
        num[i]=rand()%101;

    //升序排列;
    qsort(num,100,sizeof(int),(int (*)(const void *,const void *)) num_comp);

    //檢視已排序陣列;
    for(int i=0;i<100;i++)
        cout<<num[i]<<' ';

    //輸入要查詢的數字;
    int number=5;
    cin>>number;

    //二分查詢;
    int *p=(int *)bsearch(&number,num,SIZE(num),sizeof(int),(COMP_P)num_comp);
    
    //列印查詢資料;
    if(p!=NULL)
    {
        cout<<endl<<*p;
        cout<<endl<<"index is:"<<p-num;
    }
    else
        cout<<endl<<"not found"<<endl;
}
int num_comp(const int *a,const int *b)
{
    if(*a==*b)
        return 0;
    return *a>*b?1:-1;
}

需要注意的是,這裡定義了一個指向比較函式的指標型別COMP_P,在傳入函式地址時,將函式型別轉換一下。
而且bsearch函式返回的不是要查詢數字在陣列中的索引,而是返回查詢到的數字的指標,因此需要定義一個int *p的指標來接收這個指標,如果沒有找到返回NULL