第6课 C语言指针之qsort排序

一 回调函数

回调函数就是一个通过函数指针调用的函数。函数作为另外一个函数参数时,被调用的函数就是回调函数。

void qsort(void* base,   //base 待排序的第一个元素;
    size_t num,    //num 待排序元素个数;
    size_t size,   //size 待排序元素大小,单位是字节;
    int(*compar)(const void*, const void*) //compar是函数指针,指向的函数能够比较2个元素;
    );

void*   (地址垃圾桶)通用指针类型,可接收任意类型地址,不支持指针加减或解应用;

int a = 10; 
int* p = &a;
// char* p = &a; 类型不符报错
void* p = &a;  //void*即使类型不符仍然不会报错

       1,对整形数组排序

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>  //包含一个输入输出的文件
#include <stdlib.h>
#include <string.h>

int com_int(const void*e1, const void*e2)
{
	return *(int*)e1 - *(int*)e2; 
}

void print(int* p, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", *p++);
}

void test1()
{
	int arr[] = { 4,3,5,6,3,6,7,8,1,9,2 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), com_int);
	print(arr, sz);

}

int main()
{
	test1();
	return 0;
}

    2,对字符串排序

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>  //包含一个输入输出的文件
#include <stdlib.h> 
#include <string.h> 

int arr_string_arrange(const void* e1, const void* e2)
{
	return strcmp((char*)e1, (char*)e2);
}

void print_char(char * arr, int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%c ", *arr++);
	printf("\n");
}

int main()
{
	char brr[] = "addcefagb";
	int sz1 = sizeof(brr) / sizeof(brr[0]);
	qsort(brr, sz1, sizeof(brr[0]), arr_string_arrange);
	print_char(brr, sz1); // a a b c d d e f g
	return 0;
}

3,构造函数排序

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>  //包含一个输入输出的文件
#include <stdlib.h> 
#include <string.h> 


struct Stu //描述学生
{
	char name[20];  //名字
	int age; //年龄
};

// 假设按年龄比较
int cmp_stu_by_age(const void *e1, const void* e2) //必须转成需要的类型
{
	// struct Stu* 构造函数指针对象;  (struct Stu*)e1 这只是临时的,因此要括起来
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_stu_by_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void test2()
{
	struct Stu s[] = { {"zhangsan",10},{"lisi",50},{"wangwu",20} };
	int sz = sizeof(s) / sizeof(s[0]);
	// qsort(s,sz,sizeof(s[0]), cmp_stu_by_age);
	qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}

int main()
{
	test2();
	return 0;
}

二  构造qsort通用方法

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>  //包含一个输入输出的文件
#include<string.h>

int cmp(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}


Swap(char* buf1, char* buf2, size_t width)
{
	for (int i = 0; i < width; i++) //对每个字节都去排序
	{
		int tmp = *buf1;  //传尽量地址接收,然后交换变量
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++; buf2++;
	}

}


void bubble_sort(void* base, size_t sz, size_t width, int(*cmp)(const void* e1, const void* e2))
{
	for (int i = 0; i < sz - 1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, ((char*)base + (j + 1) * width)) > 0) {  //判断大小
				Swap((char*)base + j * width, ((char*)base + (j + 1) * width), width); //交换变量
			}

		}
	}
}

void print_arr(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
	printf("\n");
}

void test1()
{
	int  arr[] = { 5,2,4,1,6,9,3,7,0 };
	int  sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz, sizeof(arr[0]), cmp);
	print_arr(arr, sz);

}


struct Stu
{
	char name[20];
	int  age;
};

int  cmp_stu_age(const void* e1, const void* e2)
{
	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}

int cmp_stu_name(const void* e1, const void* e2)
{
	return (strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name));
}



void test2()
{
	struct Stu arr2[] = { {"zhangsan",30},{"lisi",80},{"wangwu",20} };
	int  sz = sizeof(arr2) / sizeof(arr2[0]);
	bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_age);  //根据年龄排序
	bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_name); //根据名字排序
	for (int i = 0; i < sz; i++)
	{
		printf("%d %s\n", arr2[i].age, arr2[i].name);
	}
}


int main()
{
	//test1();  //排序整数
	test2();  //排序构造函数
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值