C语言:qsort函数以及qsort函数模拟实现

1.了解qsort

qsort函数是C语言中的一个标准库函数,它的头文件#include<stdlib.h>,用来对于数组内的元素进行快速排列。它可以对任意数据类型进行排列,但前提是要提供相应的比较函数即可。qsort原形是:

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

1.base用来指向数组的指针,因为我们不知道比较的数据类型,所以用通用的数据类型void*来接收,base接收数组首元素地址,得到数组首元素地址后,便可以得到后面一系列的元素,来进行比较。

2.nitems是数组中的元素个数,元素不能是负数,所以用size_t(无符合整数类型)来接收。

3.size是指数组中每个元素的内存大小,也不能为负,用size_t接收。

4.compar是函数指针,用来指向一个比较函数,因为不同的数据类型比较方式不一样,比较函数也不一样,这是需要我们自己根据比较的数据,自行提供对应的比较函数

比较函数需要返回一个整数值,当两个元素相等时返回0,当第一个元素小于第二个元素,返回负数,当第一个元素大于第二个元素,返回正数

2.qosrt使用:

2.1用qsort排序整形:

#include<stdio.h>
#include<stdlib.h>
int com(const void* p1, const void* p2)
{
	return *(int*)p1 - *(int*)p2;
}
int main()
{
	int num=0, sz=0,i=0;//num数组元素个数,sz每个元素内存大小
	int arr[10] = { 1,9,2,8,3,7,4,6,5,10 };
	num = sizeof(arr) / sizeof(arr[0]);
	sz = sizeof(arr[0]);
	qsort(arr, num, sz, com);
	for ( i = 0; i < num; i++)
	{
		printf("%d ", arr[i]);
	}
	
}

代码运行结果:

1.在com函数中,每次接收两个元素进比较,比较完后,又接收后面的元素,两两进行比较,直到比较完为止。(这些都是在qsort函数内部实现的)

2.在com函数中,返回值若为正数(前一个元素大于后一个元素),前一个元素和后一个元素就交换,最后的到的就是升序的数组。这是qsort函数内部实现的

3.因为我们知道要比较的是两个整形,所以在com函数中,我们强制转换为int*,根据比较数据类型进行强制转换的

2.2用qsort排序结构数据结构:

定义一个结构体:

struct student
{
    char name[20];//名字
    int age;//年龄

};

我们可以排序名字和年龄,排列名字时(字符串),需要用到strcmp(比较字符串),它头文件#include<string.h>,基本形式strcmp(str1,str2),如果str1==str2则返回0,str1>str2则返回正数,str1<str2则返回负数。

2.2.1用代码实现用qsort排序名字:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
	char name[20];
	int age;
};
int com_name(const void* p1, const void* p2)
{
	return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name);
}
int main()
{
	int num=0, sz=0,i=0;
	struct student arr[3] = { {"zhangsan",22},{"lisi",30},{"wangwu",19}};
	num = sizeof(arr) / sizeof(arr[0]);
	sz = sizeof(arr[0]);
	qsort(arr, num, sz, com_name);
	for ( i = 0; i < num; i++)
	{
		printf("%s %d\n", arr[i].name,arr[i].age);
	}
}

运行结果:

2.2.2用代码实现用qsort排序年龄:

只需要修改比较函数内部就完成了。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
	char name[20];
	int age;
};
int com_age(const void* p1, const void* p2)
{
	return ((struct student*)p1)->age - ((struct student*)p2)->age;
}
int main()
{
	int num=0, sz=0,i=0;
	struct student arr[3] = { {"zhangsan",22},{"lisi",30},{"wangwu",19}};
	num = sizeof(arr) / sizeof(arr[0]);
	sz = sizeof(arr[0]);
	qsort(arr, num, sz, com_age);
	for ( i = 0; i < num; i++)
	{
		printf("%s %d\n", arr[i].name,arr[i].age);
	}
}

运行结果:

3.qsort函数模拟实现: 

3.1分布实现模拟qsort函数:

首先,我们要知道在qsort中进行了元素比较元素交换的操作。

首先从最简单的比较整数:

我们要定义一个比较两个元素大小的函数一个交换两个元素的函数

比较函数:

不同的数据类型进比较,强制转化类型不一样。整形数据比较,就强转为整形比较。

int compare(void *p1,void *p2)
{
    return *(int*)p1-*(int*)p2;
}

交换函数:因为我们每次比较的数据类型不一样,比如,整形交换是一次性交换四个字节,而字符比较交换一个字节,不同的结构体数据类型大小都不一样,交换的大小都不一样。为了方便起见,我们交换时,采用一个字节一个字节交换,比如交换整形时,我们交换四次,就是四个字节。

void swap(char*p1,char*p2,size_t size)
{
    int i=0;
    char temp;
    for(i=0;i<size;i++)
    {
        temp=*p1;
        *p1=*p2;
        *p2=temp; 
        p1++;
        p2++;      
    }
}

我们再用copy_qsor函数t模拟qsort函数。

我们采用冒泡排序的思想:

void copy_qsort (void *base,size_t number,size_t size,int(*cmp)(void *p1,void *p2))
{
    int i=0,j=0;
    for(i=1;i<number;i++)
    {
         for(j=0;j<=number-1-i;j++)
        {
             if(compare((char*)base+j*size,(char*)base+(j+1)*size)>0)
                {
                    swap((char*)base+j*size,(char*)base+(j+1)*size,size);
                }       
        }   
    }
}

3.2用模拟qsort函数进行整形数据排序:

实践代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int compare(void* p1, void* p2)
{
    return *(int*)p1 - *(int*)p2;
}
void swap(char* p1, char* p2, size_t size)
{
    int i = 0;
    char temp;
    for (i = 0; i < size; i++)
    {
        temp = *p1;
        *p1 = *p2;
        *p2 = temp;
        p1++;
        p2++;
    }
}
void copy_qsort(void* base, size_t number, size_t size, int(*cmp)(void* p1, void* p2))
{
    int i = 0, j = 0;
    for (i = 1; i < number; i++)
    {
        for (j = 0; j <= number - 1 - i; j++)
        {
            if (compare((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
            {
                swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
            }
        }
    }
}
int main()
{
    int num = 0, sz = 0, i = 0;
    int arr[10] = { 1,9,2,8,3,7,6,4,10,5 };
    num = sizeof(arr) / sizeof(arr[0]);
    sz = sizeof(arr[0]);
    copy_qsort(arr, num, sz, compare);
    for (i = 0; i < num; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

运行结果

3.3用模拟qsort进行结构体排序:

这里我就只排序名字,年龄排序如2.2.2

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
    char name[20];
    int age;
};
int compare(void* p1, void* p2)
{
    return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name);
}
void swap(char* p1, char* p2, size_t size)
{
    int i = 0;
    char temp;
    for (i = 0; i < size; i++)
    {
        temp = *p1;
        *p1 = *p2;
        *p2 = temp;
        p1++;
        p2++;
    }
}
void copy_qsort(void* base, size_t number, size_t size, int(*cmp)(void* p1, void* p2))
{
    int i = 0, j = 0;
    for (i = 1; i < number; i++)
    {
        for (j = 0; j <= number - 1 - i; j++)
        {
            if (compare((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
            {
                swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
            }
        }
    }
}
int main()
{
    int num = 0, sz = 0, i = 0;
    struct student arr[3] = { {"zhangsan",19},{"lisi",28},{"wangwu",23}};
    num = sizeof(arr) / sizeof(arr[0]);
    sz = sizeof(arr[0]);
    copy_qsort(arr, num, sz, compare);
    for (i = 0; i < num; i++)
    {
        printf("%s %d\n", arr[i].name,arr[i].age);
    }
    return 0;
}

运行结果:

希望我写的能给大家带来帮助,如有错误希望大家指出,谢谢大家支持。

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值