IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言中qsort函数的讲解应用与仿写 -> 正文阅读

[C++知识库]C语言中qsort函数的讲解应用与仿写

目录

qsort

qsort基本介绍

void*

void*的基本概念

void*的使用

qsort的使用


qsort

如果是对于整型的排序,有冒泡排序法或选择排序法,那么若要排序浮点型,结构体等等,虽然我们能够写出若干个这样的函数来排列,但最终是不是都会过于复杂了?我们是否能够用一种函数来概括所有排序的情况?

答案当然是能够做到的。此时要用到系统自带的qsort()函数。

那么什么又是qsort呢?

qsort基本介绍

在MSDN中查找,我们会发现qsort是库函数,采用的是快速排序法。且需要引入头文件<stdlib.h>来使用。在MSDN中,我们可以知道该函数的参数为下面代码所示:

void qsort( void *base,
            size_t num,
            size_t width, 
            int (__cdecl *compare )(const void *elem1, const void *elem2 ) );


根据MSDN的解释我们能够知道每个参数的作用意义:

  • base——函数名(地址)
  • num——要排序的个数
  • width——每个元素所占的字节大小
  • elem1、elem2——是用来定位索要对比的两个元素大小的指针
  • int(* compare)(const void* elem1,const void* elem2)——用来比较的一个函数指针

void*

在了解qsort函数如何使用前,我们先理清这个平常并不太熟悉的指针类型——void* 型

void*的基本概念

void* 是一种无具体类型的指针,当我们创建了一个void*变量如:void* e1时,若在程序中写下*e1,程序会报错,指出非法的间接寻址。void*类型不能直接进行解引用操作,也不能直接进行+-操作。

正因为void是一种无类型指针,所以每种类型的地址我们都可以用void*指针来接收

所以,由上面我们可以知道,利用void*能够接收所有类型的指针,从而void*是达到在qsort中使用能够接收所有类型的数据进行排序的前提。

void*的使用

强制类型转换——void接收到传入地址后我们可以通过强制类型转换来使用它。就那转换成int来举例:

int cmp_int(const void* elem1, const void* elem2)
{
  *(int*)elem1;//此时不会报错
  *(int*)elem2;
}
int main()
{
  int arr[] = { 0,4,2,5,8,9,1,3,7,6 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  Print(arr, sz);
  return 0;
}

在我们将void*强制类型转换成int后,就可以当作是int*来使用了。

qsort的使用

在了解了void*后,我们还要知道qsort函数返回值返回的是什么,通过查看MSDN我们知道,若第一个元素小于第二个元素,则返回<0,若第一个元素等于第二个,则返回0,若第一个元素大于第二个元素,则返回>0。

所以在我们可以将cmp函数写出了,如下面代码所示:

int cmp_int(const void* elem1, const void* elem2)
{
  if (*(int*)elem1 < *(int*)elem2)
  {
    return -1;
  }
  else if (*(int*)elem1 > *(int*)elem2)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}
int main()
{
  int arr[] = { 0,4,2,5,8,9,1,3,7,6 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  return 0;
}

因为要求的是返回值<、>或者=,所以也可以简化为:

int cmp_int(const void* elem1, const void* elem2)
{
  return *(int*)elem1 - *(int*)elem2;
}
int main()
{
  int arr[] = { 0,4,2,5,8,9,1,3,7,6 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  return 0;
}

此时已经完善好了qsort的所有参数,也就相当于已经将我们要排序的数据已经全部排序好了,试着将所有元素打印出来:

#include <stdio.h>
void Print(int* arr, int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", arr[i]);
  }
  printf("\n");
}

int cmp_int(const void* elem1, const void* elem2)
{
  return *(int*)elem1 - *(int*)elem2;
}
int main()
{
  int arr[] = { 0,4,2,5,8,9,1,3,7,6 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  //bubble_sort(arr, sz);
  qsort(arr, sz, sizeof(arr[0]), cmp_int);
  Print(arr, sz);
  return 0;
}

下面用结构体来使用qsort:

(比较名字)

int cmp_stu_name(const void* elem1, const void* elem2)
{
  return (strcmp((*(struct Stu*)elem1).name, (*(struct Stu*)elem2).name));
}

void print_stu(struct Stu* arr,int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%s %d %.2f", (*(arr+i)).name, (*(arr+i)).age, (*(arr+i)).score);
    printf("\n");
  }
}

int main()
{
  struct Stu arr[] = { {"Zhangsan",20,95.0f},{"Lisi",22,98.6f},{"Wangwu",15,78.9f} };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_stu_name);
  print_stu(arr, sz);
  return 0;
}

(比较分数)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Stu
{
  char name[20];
  int age;
  float score;
};

void print_stu(struct Stu* arr, int sz)
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%s %d %.2f", (*(arr + i)).name, (*(arr + i)).age, (*(arr + i)).score);
    printf("\n");
  }
}

int cmp_stu_score(const void* elem1, const void* elem2)
{
  if ((*(struct Stu*)elem1).score<(*(struct Stu*)elem2).score)
  {
    return -1;
  }
  else if ((*(struct Stu*)elem1).score > (*(struct Stu*)elem2).score)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int main()
{
  struct Stu arr[] = { {"zhangsan",20,85.4f},{"lisi",22,95.6f},{"wangwu",15,78.6f} };
  int sz = sizeof(arr) / sizeof(arr[0]);
  qsort(arr, sz, sizeof(arr[0]), cmp_stu_score);
  print_stu(arr, sz);
  return 0;
}

在知道了qsort是如何使用之后,我们不妨再深究探讨一个问题:为什么qsort要设计四个参数?我们是否有可以仿照qsort函数,写出一个属于自己的可以将任何类型排序的函数。

下面是经过了小绿长时间的研究后,写出的以冒泡排序法为原理的一串代码,成功仿照了qsort的功能:

#include <stdio.h>

swap(char* elem1, char* elem2, int width)
{
  int i = 0;
  for (i = 0; i < width; i++)
  {
    char str = *(elem1);
    *elem1 = *elem2;
    *elem2 = str;
    elem1++;
    elem2++;
  }
}

int cmp_int(const void* elem1, const void* elem2)
{
  if (*(int*)elem1 > *(int*)elem2)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

void q_bubble_sort(void* arr, int sz, int width, int (*cmp)(const void* elem1, const void* elem2))
{
  int i = 0;
  int j = 0;
  for (i = 0; i < sz-1; i++)
  {
    for (j = 0; j < sz - 1 - i; j++)
    {
      if (cmp((char*)arr+width*j, (char*)arr+width*(j+1)) > 0)
      {
        swap((char*)arr + width * j, (char*)arr + width * (j + 1),width);
      }
    }
  }
}

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

int main()
{
  int arr[] = { 0,4,2,5,8,9,1,3,7,6 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  q_bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);
  print_int(arr, sz);
  return 0;
}

在这里我们要注意的是,我只写了排序int型数据的情况,而在排序前提类型时的cmp函数要重新写出来,才能使用。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:10:02  更:2022-03-08 22:14:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:40:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码