Qsort函数实现对各类型数组中元素的排序(思路简单)

简介: Qsort函数实现对各类型数组中元素的排序(思路简单)

函数介绍

作用:对指向的数组中的数组元素进行快速排序

头文件: stdlib.h

函数原型:void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));

参数解释:

  • base: 指向需要排序的数组首元素的指针
  • num: 数组中元素个数
  • size: 每个元素大小(以字节为单位)
  • compar: 比较函数,用于确定两个元素之间的顺序关系

比较函数需要满足以下条件:

  1. 第一个参数小于第二个参数,返回负数
  2. 两个参数相等,返回零
  3. 第一个参数大于第二个参数,返回正数

Void*类型的指针是通用指针,可以接受任意类型的地址

函数使用案例:

(一)对int型数组的排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//排序整型数组
int my_cmp(const void* a, const void* b)
{
  return (*(int*)a - *(int*)b);
}
int main()
{
  int num[3] = { 2,5,3 };
  qsort(num, 3, sizeof(num[0]), my_cmp);
  for (int i = 0; i < 3; i++)
  {
    printf("%d ", num[i]);
  }
  return 0;
}

(二)对char型数组的排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//排序char型数组
int my_cmp(const void* a, const void* b)
{
  return (*(char*)a - *(char*)b);
}
int main()
{
  char num[] = { 'a','c','b' };
  qsort(num, 3, sizeof(num[0]), my_cmp);
  for (int i = 0; i < 3; i++)
  {
    printf("%c ", num[i]);
  }
  return 0;
}

(三)对浮点型数组的排序

注意事项:由于浮点数存在精度问题,在计算机内部表示时可能会出现舍入误差,所以如果还是在上面的基础上进行简单修改的化就会导致数组中的3.14>3.20的情况发生,所以需要更加严谨的

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//排序浮点型型数组
int my_cmp(const void* a, const void* b)
{
    double num1 = *(const double*)a;
    double num2 = *(const double*)b;
    if (num1 < num2)
        return -1;
    else if (num1 > num2)
        return 1;
    return 0; // 相等情况
}
int main()
{
    double arr[] = { 3.14, 5.16, 3.20 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    qsort(arr, sz, sizeof(arr[0]), my_cmp);
    for (int i = 0; i < sz; i++)
    {
        printf("%lf ", arr[i]);
    }
    return 0;
}

(四)对结构体类型的排序

同时包含了对字符串数组的排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//按单个字节交换位置
void Swap(char* buf1, char* buf2, size_t width)
{
  int i = 0;
  for (i = 0; i < width; i++)
  {
    char tmp = *buf1;
    *buf1 = *buf2;
    *buf2 = tmp;
    buf1++;
    buf2++;
  }
}
//模拟qsort函数
void bubble_sort(void* base, size_t sz, size_t width, int (*cmp)(const void* e1, const void* e2))
{
  int i = 0;
  for (i = 0; i < sz - 1; i++)
  {
    int j = 0;
    for (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);
      }
    }
  }
}
//声明结构体(以后会写到,现在先用着)
struct Stu {
  char name[20];
  int age;
};
//计算年龄差值与0的关系
int cmp_stu_by_age(const void* e1, const void* e2)
{
  return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//利用strcmp函数比较字符的ASCII码
int cmp_stu_by_name(const void* e1, const void* e2)
{
  return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//测试bubble_sort排序结构体数据
void test2()
{
    struct Stu arr2[] = { {"zhansgan", 15}, {"lisi", 35},{"wangwu", 32} };
    int sz = sizeof(arr2) / sizeof(arr2[0]); //sz = 3 , sizeof(arr2[0]) = 24
    //bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_by_age); 
    bubble_sort(arr2, sz, sizeof(arr2[0]), cmp_stu_by_name);
}
int main()
{
  test2();
  return 0;
}

对于名字的排序结果:

对于年龄的排序结果:

(五) 模仿qsort的功能实现一个通用的冒泡排序

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Swap(char* buf1, char* buf2, size_t width)
{
  int i = 0;
  for (i = 0; i < width; i++)
  {
    char 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))
{
  int i = 0;
  for (i = 0; i < sz - 1; i++)
  {
    int j = 0;
    for (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);
      }
    }
  }
}
int cmp_int(const void* e1, const void* e2)
{
  return *(int*)e1 - *(int*)e2;
}
void print_arr(int arr[], int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}
void test1()
{
  int arr[] = { 3,2,5,6,8,7,10,9 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  print_arr(arr, sz);
  bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
  print_arr(arr, sz);
}
int main()
{
  test1();
  return 0;
}

~over~

相关文章
|
存储
STM32F103标准外设库——GPIO 输入、输出 (五)
STM32F103标准外设库——GPIO 输入、输出 (五)
875 0
STM32F103标准外设库——GPIO 输入、输出 (五)
|
数据采集 并行计算 Java
【文末送书】Python高并发编程:探索异步IO和多线程并发
【文末送书】Python高并发编程:探索异步IO和多线程并发
458 0
|
10月前
|
SQL 安全 网络安全
网络安全的护城河:漏洞防御与加密技术的深度解析
【10月更文挑战第37天】在数字时代的浪潮中,网络安全成为守护个人隐私与企业资产的坚固堡垒。本文将深入探讨网络安全的两大核心要素——安全漏洞和加密技术,以及如何通过提升安全意识来强化这道防线。文章旨在揭示网络攻防战的复杂性,并引导读者构建更为稳固的安全体系。
318 1
|
5月前
|
安全 前端开发 Java
理解 Spring Security 的 HttpMethod 和路径匹配
本文深入解析了Spring Security中`HttpMethod`与路径匹配的使用方法及其常见问题。通过具体示例,阐明了如何针对不同HTTP方法(如GET、POST)和路径(如`/api/products`与`/products`)设置权限,避免用户绕过限制访问核心数据。同时,强调了配置顺序和角色前缀的重要性,并提供了最佳实践,帮助开发者精准控制应用的安全性。
133 1
|
6月前
|
设计模式 Java 数据库
06.依赖倒置原则介绍
依赖倒置原则是面向对象设计六大原则之一,强调高层模块不应依赖低层模块,两者应依赖于抽象。通过依赖接口或抽象类而非具体实现,降低模块耦合度,提升系统灵活性和可维护性。本文详解该原则的概念、目标、思想及其实现方式(如依赖注入),并结合多数据库操作、用户购买家电、发送消息等实际案例,深入探讨其应用与优缺点。
417 4
|
11月前
零基础入门金融风控之贷款违约预测的Task1:赛题理解
零基础入门金融风控之贷款违约预测的Task1:赛题理解
175 4
|
缓存 关系型数据库 PostgreSQL
PostgreSQL自增ID的初始化语句
【5月更文挑战第10天】PostgreSQL自增ID的初始化语句
507 2
|
Java API
LOG4J2-MDC-全链路跟踪等功能研究
LOG4J2-MDC-全链路跟踪等功能研究
530 0
|
Linux iOS开发 MacOS
BACnet 调试工具 工程师必备
BACnet是由ASHRAE开发的标准通信协议,专用于楼宇自动化和控制网络。它支持对象访问、报警与事件处理、文件传输及远程设备管理等功能,实现了跨平台操作。BACnet Explorer作为一款强大的工具,不仅便于浏览与控制BACnet设备,还内置了设备模拟器以辅助调试工作。其用户友好的界面设计确保了高效便捷的操作体验。
536 3
BACnet 调试工具 工程师必备
|
设计模式 安全 Java
程序与技术分享:Context详解
程序与技术分享:Context详解
371 0