qsort 说明

标准库详解

qsort包含在<stdlib.h>头文件中,此函数根据你给的比较条件进行快速排序,通过指针移动实现排序。排序之后的结果仍然放在原数组中。使用qsort函数必须自己写一个比较函数。

函数原型:

void qsort ( void * base, size_t num, size_t size, int ( * comparator ) ( const void *, const void * ) );

用法以及参数说明:

Sorts the num elements of the array pointed by base, each element size bytes long, using the comparator function to determine the order.

The sorting algorithm used by this function compares pairs of values by calling the specified comparator function with two pointers to elements of the array.

The function does not return any value, but modifies the content of the array pointed by base reordering its elements to the newly sorted order.

base Pointer to the first element of the array to be sorted.(数组起始地址)
num Number of elements in the array pointed by base.(数组元素个数)
size Size in bytes of each element in the array.(每一个元素的大小)
comparator Function that compares two elements.(函数指针,指向比较函数)
1、The function must accept two parameters that are pointers to elements, type-casted as void*. These parameters should be cast back to some data type and be compared.
2、The return value of this function should represent whether elem1 is considered less than, equal to, or greater than elem2 by returning, respectively, a negative value, zero or a positive value.
Return Value none (无返回值)


一、对int类型数组排序

int num[100];

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

qsort(num,100,sizeof(num[0]),cmp);

二、对char类型数组排序(同int类型)

char word[100];

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

qsort(word,100,sizeof(word[0]),cmp);

三、对double类型数组排序

double in[100];

int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}

qsort(in,100,sizeof(in[0]),cmp);

四、对结构体一级排序

struct Sample
{
double data;
int other;
}s[100]

//按照data的值从小到大将结构体排序

int cmp( const void *a ,const void *b)
{
return (*(Sample *)a).data > (*(Sample *)b).data ? 1 : -1;
}

qsort(s,100,sizeof(s[0]),cmp);

五、对结构体二级排序

struct Sample
{
int x;
int y;
}s[100];

//按照x从小到大排序,当x相等时按照y从大到小排序

int cmp( const void *a , const void *b )
{
struct Sample *c = (Sample *)a;
struct Sample *d = (Sample *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}

qsort(s,100,sizeof(s[0]),cmp);

六、对字符串进行排序

struct Sample
{
int data;
char str[100];
}s[100];

//按照结构体中字符串str的字典顺序排序

int cmp ( const void *a , const void *b )
{
return strcmp( (*(Sample *)a).str , (*(Sample *)b).str );
}

qsort(s,100,sizeof(s[0]),cmp);

附加一个完整点的代码,对字符串二维数组排序:

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

char s[2001][1001];

int cmp(const void *a, const void *b){
return strcmp((char *)a,(char *)b);
}

int main(){
int i,n;
scanf("%d",&n);
getchar();
for(i=0;i<n;i++) gets(s[i]);
qsort(s,n,1001*sizeof(char),cmp);
for(i=0;i<n;i++) puts(s[i]);
return 0;
}

一个例子

最近由于学习Linux C程序设计等内容再次遇到头疼的指针,所以特此重新学习下指针和C++的面向对象编程相关的知识,发现以前不会的现在理解起来很easy。

qsort函数原型(C语言标准库函数)
      功 能: 使用快速排序例程进行排序
    用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *));
    参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针,用于确定排序的顺序 


这里就用到了指针,void*个人认为可以理解成Java里的Object, int (*fcmp)(const void *,const void *):函数指针,const就是说明后面的参数不可以改变,增加程序的健壮性。

排序就需要用到交换,即令人头疼的swap函数

1、最简单的实现


[cpp] view plaincopyprint?
void swap(int a,int b){  
    int temp;  
    temp = a;a = b; b = temp;  
}  

void swap(int a,int b){
	int temp;
	temp = a;a = b; b = temp;
}此种方法在各种C/C++教科书上都说不能实现a和b的交换,这里就不解释了 

2、指针形参


[cpp] view plaincopyprint?
void swap(int&,int&);  
  
void swap(int *a,int *b){  
    int temp;  
    temp = *a;*a = *b; *b = temp;  
}  

void swap(int&,int&);

void swap(int *a,int *b){
	int temp;
	temp = *a;*a = *b; *b = temp;
}这个肯定能实现交换,&直接取址,*间接取址 

3、引用形参


[cpp] view plaincopyprint?
void swap(int&,int&);  
  
void swap(int &a,int &b){  
    int temp;  
    temp = a;a = b; b = temp;  
}  

void swap(int&,int&);

void swap(int &a,int &b){
	int temp;
	temp = a;a = b; b = temp;
}4、异或运算 


[cpp] view plaincopyprint?
a ^= b;  
b ^= a;  
a ^= b;  
//a^b^a = b  

a ^= b;
b ^= a;
a ^= b;
//a^b^a = b5、qsort源码用到的 


[cpp] view plaincopyprint?
void swap(char *a,char* b,int width){  
    char temp;  
    while(width --){  
        temp = *a,*a++ = *b,*b++ = temp;  
    }  
}  

void swap(char *a,char* b,int width){
    char temp;
    while(width --){
        temp = *a,*a++ = *b,*b++ = temp;
    }
}width:待交换元素的占用空间大小,此种方法和第三种方法是同样的原理 




QSORT源码:


[cpp] view plaincopyprint?
#include <iostream>   
#include <cstring>   
using namespace std;  
  
struct Node{  
    char *word;  
    int cnt;  
};  
  
void qsort(void *base,int nleft, int nright,int(*fcmp)(void*,void*));  
int cmp(void* a,void* b){//(int*)属强制转换,再*间接取址   
    return *(int *)a - *(int *)b;  
}  
  
int cmp2(void* a,void* b){  
    Node pa = *(Node *)a;  
    Node pb = *(Node *)b;  
    return strcmp(pa.word,pb.word);  
}  
  
void swap(char *a,char* b,int width){  
    char temp;  
    while(width --){  
        temp = *a,*a++ = *b,*b++ = temp;  
    }  
}  
void qsort(void* base,int nleft,int nright,int width,int (*fcmp)(void*,void*)){  
    if(nleft >= nright) return;  
    char *lo = (char*)base + width*nleft;  
    char *hi = (char*)base + width*((nleft + nright)/2);  
    swap(lo,hi,width);  
    int x = nleft;  
    lo = (char*)base + width * nleft;//standard   
    //cout<<"St: "<<(*(Node*)lo).word<<endl;   
    for(int i = nleft + 1 ; i <= nright ; i ++){  
        hi = (char*)base + width * i;  
        if(fcmp(lo,hi) < 0){  
            x ++;  
            char *ll = (char*)base + width * x;  
            swap(ll,hi,width);  
        }  
    }  
    hi = (char*)base + width * x;  
    swap(lo,hi,width);  
    qsort(base,nleft,x - 1,width,fcmp);  
    qsort(base,x + 1,nright,width,fcmp);  
}  
  
int main(){  
    int a[10] = {1,2,3,4,5,6,7,8,9,10};  
    qsort(a,0,9,sizeof(int),cmp);  
    for(int i = 0 ; i < 10 ; i ++) cout<<a[i]<<endl;  
    Node node[5] = {{"xkey",10},{"color",3},{"void",4},{"static",5},{"while",2}};  
    qsort(node,0,4,sizeof(node[0]),cmp2);  
    for(int i = 0 ; i < 5 ; i ++){  
        cout<<node[i].word<<" "<<node[i].cnt<<endl;  
    }  
    return 0;  
}  

#include <iostream>
#include <cstring>
using namespace std;

struct Node{
    char *word;
    int cnt;
};

void qsort(void *base,int nleft, int nright,int(*fcmp)(void*,void*));
int cmp(void* a,void* b){//(int*)属强制转换,再*间接取址
    return *(int *)a - *(int *)b;
}

int cmp2(void* a,void* b){
    Node pa = *(Node *)a;
    Node pb = *(Node *)b;
    return strcmp(pa.word,pb.word);
}

void swap(char *a,char* b,int width){
    char temp;
    while(width --){
        temp = *a,*a++ = *b,*b++ = temp;
    }
}
void qsort(void* base,int nleft,int nright,int width,int (*fcmp)(void*,void*)){
    if(nleft >= nright) return;
    char *lo = (char*)base + width*nleft;
    char *hi = (char*)base + width*((nleft + nright)/2);
    swap(lo,hi,width);
    int x = nleft;
    lo = (char*)base + width * nleft;//standard
    //cout<<"St: "<<(*(Node*)lo).word<<endl;
    for(int i = nleft + 1 ; i <= nright ; i ++){
        hi = (char*)base + width * i;
        if(fcmp(lo,hi) < 0){
            x ++;
            char *ll = (char*)base + width * x;
            swap(ll,hi,width);
        }
    }
    hi = (char*)base + width * x;
    swap(lo,hi,width);
    qsort(base,nleft,x - 1,width,fcmp);
    qsort(base,x + 1,nright,width,fcmp);
}

int main(){
    int a[10] = {1,2,3,4,5,6,7,8,9,10};
    qsort(a,0,9,sizeof(int),cmp);
    for(int i = 0 ; i < 10 ; i ++) cout<<a[i]<<endl;
    Node node[5] = {{"xkey",10},{"color",3},{"void",4},{"static",5},{"while",2}};
    qsort(node,0,4,sizeof(node[0]),cmp2);
    for(int i = 0 ; i < 5 ; i ++){
        cout<<node[i].word<<" "<<node[i].cnt<<endl;
    }
    return 0;
}

该qsort的性能没有检测,可能比对应的某种数据类型的自己写qsort要慢,应该是乘法使用过多的原因,但是优点就是能够适用各种数据类型。 

深入分析qsort库函数(一)http://www.programfan.com/blog/article.asp?id=14298
深入分析qsort库函数(二)http://blog.pfan.cn/accelerator/14363.html
深入分析qsort库函数(三)http://blog.pfan.cn/accelerator/14463.html






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值