1、 qsort 函数
1.1、qsort 函数排列结构体
在这里,我们创建结构体类型的数组,用于 qsort 函数的传参。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Stu//创建结构体变量
{
char name[30];
int age;
};
struct Stu arr[] = { { "zhangsan", 18 }, { "lisi", 20 }, { "wangwu", 38 } };
void Print(struct Stu* p, int sz)//打印函数
{
for (int i = 0; i < sz; i++)
{
printf("%s: %d\n", p->name, p->age);
p++;
}
}
cmp_str_by_age(const void* p1, const void* p2)//排年龄函数
{
return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}
test1()//按年龄大小
{
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_str_by_age);
Print(arr, sz);
}
cmp_str_by_name(const void* p1, const void* p2)//排姓名函数
{
return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}
test2()//按姓名
{
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_str_by_name);
Print(arr, sz);
}
int main()
{
test1();
printf("-------------------------\n");
test2();
return 0;
}
这里讲两点:
1、结构成员访问操作符: ->
使用方法为:结构体指针 -> 成员变量。上面代码中, ((struct Stu*)p1)->age 也可以换为 *(struct Stu*)p1.age 。
2、 strcmp 函数
使用方法为,向函数中传入两个字符串类型的数据,比较对应位置字符的 ASCII 码值的大小。以顺序为例,若前一个字符串对应位置字符的 ASCII 码值应大于后一个,返回大于0的值;相等返回0,小于返回小于0的值。
1.2、 qsort 函数的模拟实现
既然要实现 qsort 函数,那么向其中传入的参数,也应该是:首元素地址、元素个数、元素大小、比较函数。
#include<stdio.h>
int int_cmp(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
}
void test1()
{
int arr[] = { 4,5,2,7,9,12,34,101 };
int count = sizeof(arr) / sizeof(arr[0]);
Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
}
int main()
{
test1();//实现整型值的排序
return 0;
}
将这个函数的名字取为 Bubble_qsort ,是因为我们将用冒泡排列的方式来模拟实现 qsort 函数。
所以,我们要交代趟数,也要交代每趟交换数据的次数。
而交换操作中,我们可以将每两个数(的地址)传入 int_cmp 函数中,观察返回的值。若返回正数值,则再创建一个交换函数。
但是, void* 类型的指针不能进行任何操作。也许会用强制类型转换,转换成什么? int* ?但这可是在模拟 qsort 函数,这个函数原来是可以排列任意类型的数据的。
所以,我们不妨将 void* 类型,强制转换成 char* 类型 。
#include<stdio.h>
int int_cmp(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void Swap(char* buf1, char* buf2)
{
}
void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{
for (int i = 0; i < count - 1; i++)
{
for (int j = 0; j < count - i - 1; j++)
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
void test1()
{
int arr[] = { 4,5,2,7,9,12,34,101 };
int count = sizeof(arr) / sizeof(arr[0]);
Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
}
int main()
{
test1();//实现整型值的排序
return 0;
}
而在交换函数中,既然地址已被强制转换成 char* ,那么我们就不能一次性交换干净,而是一点一点交换。交换的次数,自然是元素的大小。
#include<stdio.h>
void Print(int arr[], int count)//打印函数
{
for (int i = 0; i < count; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int int_cmp(const void* p1, const void* p2)//比较函数
{
return *(int*)p1 - *(int*)p2;
}
void Swap(char* buf1, char* buf2, int size)//交换函数
{
for (int i = 0; i < size; i++)
{
char tmp = *(buf1 + i);
*(buf1 + i) = *(buf2 + i);
*(buf2 + i) = tmp;
}
}
void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{ //模拟 qsort 的函数
for (int i = 0; i < count - 1; i++)
{
for (int j = 0; j < count - i - 1; j++)
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
void test1()
{
int arr[] = { 4,5,2,7,9,12,34,101 };
int count = sizeof(arr) / sizeof(arr[0]);
Print(arr, count);
Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
Print(arr, count);
}
int main()
{
test1();//实现整型值的排序
return 0;
}
这样一来,这个函数连结构体都能排列。但是要加一点比较函数代码:
#include<stdio.h>
struct Stu//创建结构体
{
char name[30];
int age;
};
void Print(int arr[], int count)//打印函数
{
for (int i = 0; i < count; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void Print1(struct Stu* p, int sz)//打印结构体
{
for (int i = 0; i < sz; i++)
{
printf("%s: %d\n", p->name, p->age);
p++;
}
}
int int_cmp(const void* p1, const void* p2)//比较函数
{
return *(int*)p1 - *(int*)p2;
}
int cmp_str_by_name(const void* p1, const void* p2)//比较字符串
{
if (strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name) > 0)
return 1;
else if (strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name) < 0)
return -1;
else
return 0;
}
void Swap(char* buf1, char* buf2, int size)//交换函数
{
for (int i = 0; i < size; i++)
{
char tmp = *(buf1 + i);
*(buf1 + i) = *(buf2 + i);
*(buf2 + i) = tmp;
}
}
void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{ //模拟 qsort 的函数
for (int i = 0; i < count - 1; i++)
{
for (int j = 0; j < count - i - 1; j++)
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
void test1()
{
int arr[] = { 4,5,2,7,9,12,34,101 };
int count = sizeof(arr) / sizeof(arr[0]);
Print(arr, count);
Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
Print(arr, count);
}
void test2()
{
struct Stu arr[] = { { "zhangsan", 18 }, { "lisi", 20 }, { "wangwu", 38 } };
int count = sizeof(arr) / sizeof(arr[0]);
Print1(arr, count);
printf("-------------------------\n");
Bubble_qsort(arr, count, sizeof(arr[0]), cmp_str_by_name);
Print1(arr, count);
}
int main()
{
//test1();//实现整型值的排序
test2();//实现结构体的排列
return 0;
}