课外拓展2.实现qsort函数及模拟实现qsort函数

简介: 课外拓展2.实现qsort函数及模拟实现qsort函数

qsort函数和qsort函数的模拟实现


一,qsort函数的实现


#define _CRT_SECURE_NO_WARNINGS 1
//qsort函数
#include<stdio.h>
#include<stdlib.h>
void print(int arr[], int sz) {
  for (int i = 0; i < sz; i++)
    printf("%d ",arr[i]);
  printf("\n");
}
int compare(const void *e1,const void *e2) {
  return *(int*)e1 - *(int*)e2;
}
int main() {
  int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  //排序
  qsort(arr,sz,sizeof(arr[0]),compare);
  //输出
  print(arr, sz);
  return 0;
}
//qsort函数的基本结构(快速排序)
//void qsort(void* base, size_t num, size_t size, int (*compare)(const void*, const void*));
//void* base指的是排序数据首元素的地址。
//size_t num指的是排序数据的个数;
//size_t size指的是每个元素的大小(占几个字节);因为传进来的数据首元素的类型未知,需要认为的输入字节大小;
//int (*compare)(const void*, const void*)指的是一个函数指针;指向一个函数。这个是留给使用者写的自定义函数。
//因为qsort函数适用于所有类型的比较排序,所以指针类型都是void,但是使用者是一定知道比较的数据类型,故把这个函数留给使用者写
//
//int compare(const void* e1, const void* e2) {
//  return *(int*)e1 - *(int*)e2;
//}
//我们来分析一下这个该由我们自己书写的函数
//首先,参数是两个无类型的空指针,代表着这个函数可以用于任何类型的数据相比较
//这个函数的返回值一定是int整型,因为在qsort函数中是根据这个函数的返回值进行排序的,返回值大于0是就是升序排序,
//返回值小于0就是降序排序。


qsort函数的基本结构(快速排序)

void qsort(void* base, size_t num, size_t size, int (*compare)(const void*, const void*));

void* base指的是排序数据首元素的地址。

size_t num指的是排序数据的个数;

size_t size指的是每个元素的大小(占几个字节);因为传进来的数据首元素的类型未知,需要认为的输入字节大小;

       int (*compare)(const void*, const void*)指的是一个函数指针;指向一个函数。这个是留给使用者写的自定义函数。

       因为qsort函数适用于所有类型的比较排序,所以指针类型都是void,但是使用者是一定知道比较的数据类型,故把这个函数留给使用者写

int compare(const void* e1, const void* e2) {

   return *(int*)e1 - *(int*)e2;

}

       我们来分析一下这个该由我们自己书写的函数

首先,参数是两个无类型的空指针,代表着这个函数可以用于任何类型的数据相比较

           这个函数的返回值一定是int整型,因为在qsort函数中是根据这个函数的返回值进行排序的,返回值大于0是就是升序排序,

返回值小于0就是降序排序。


二,qsort函数的模拟实现


//模拟实现qsort函数
#include<stdio.h>
//交换函数(也可以不单独写成函数,但是我觉得主要可读性更好)
void swap(char* buf1, char* buf2,size_t width) {
  int i;
  for (i = 0; i < width; i++) {
    char temp = *buf1;
    *buf1 = *buf2;
    *buf2 = temp;
    buf1++;
    buf2++;
  }
}
//写qsort必须写的函数,必须由使用者写,虽然我们这里是模拟实现qsort函数,但是仍需要写这个。
int compare(const void* e1, const void* e2) {
  //根据返回值进行排序(来绝对是升序还是降序)
  return *(char*)e1 - *(char*)e2;
}
void bubble_sort(void* base, size_t sz, size_t width, int (*compare)(const void*, const void*)) {
  int i, j;
  //外层循环控制总趟数
  for (i = 0; i < sz-1; i++) {//这里一定是sz减一,sz是数组长度,下标只能到sz-1;
    for (j = 0; j < sz - i- 1; j++) {
      //这个地方是妥妥的重点了,为什么要强制类型转换为char* 类型?
      //其实这个地方我觉得转换为其他类型也行,但是qsort函数是可以对所有数据类型进行排序的,如果只是对单一的一种数据排序,那的确是可以的
      //但是我们这里是模拟实现qsort函数的功能,故,我们这里转换为char* 类型
      //还有一个原因,char*类型的指针解引用时只走一个字节,众所周知,字节是代码的最小存储单位了,其他无论什么类型的数据都是以字节论的
      if (compare((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
        swap(((char*)base + j * width), ((char*)base + (j + 1) * width),width);
      //我们再来理解一下这个(char*)base + j * width是什么意思呢?
      //首先这个char*我是已经将过了的,接下来我们要解释的就是j*width的含义
      //因为我们对未知类型的数据进行排序,(int*)+1是走四个字节,但对它本身来说就只移动了一个元素长度
      //那如果是(int*)+i呢?我们是不是就可以理解为从头开始往后面走了i个元素,拿这个例子与上面一对比,这就十分明确了
      //j*width的意思就是待排序数据一个元素所占用的长度,也就是往后面移动了一位。
    }
  }
}
int main() {
  int arr[] = { 1,3,5,7,9,2,4,6,8,0 };
  bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), compare);
  int i = 0;
  for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    printf("%d",arr[i]);
  }
  printf("\n");
  char arr1[] = "hello world";//这里我准备了两个例子供大家参考
  bubble_sort(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(arr1[0]), compare);
  for (i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
    printf("%c",arr1[i]);
  printf("\n");
  return 0;
}


qsort函数,俗称快排,它可以对任意数据类型的数据进行排序,这是很方便的,希望大家一定要搞熟。


希望大家能学到东西,静待大家的斧正和指教。

目录
相关文章
|
8月前
|
算法 程序员 数据处理
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
|
8月前
|
算法 调度
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(二)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
71 0
|
7月前
|
存储 C++
C++初阶学习第十一弹——探索STL奥秘(六)——深度刨析list的用法和核心点
C++初阶学习第十一弹——探索STL奥秘(六)——深度刨析list的用法和核心点
61 7
|
8月前
|
算法 C语言 C++
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(一)
三子棋游戏设计的核心是对二维数组的把握和运用。
102 1
|
8月前
|
C语言
万字详解:C语言三子棋进阶 + N子棋递归动态判断输赢(二)
我们可以通过创建并定义符号常量NUMBER,来作为判断是否胜利的标准。如三子棋中,令NUMBER为3,则这八个方向中有任意一个方向达成3子连珠,则连珠的这个棋子所代表的玩家获胜。
84 1
|
8月前
|
存储 算法
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(三)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
70 0
|
8月前
|
存储 算法 搜索推荐
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理(一)
【软件设计师备考 专题 】算法探索:排序、查找、数值计算和字符串处理
158 0
|
存储 算法
基础算法 - 常见算法模板题(最简洁写法)【下】
基础算法 - 常见算法模板题(最简洁写法)【下】
|
8月前
|
算法 索引
二分查找算法案例
二分查找算法案例
77 0
|
8月前
|
搜索推荐 算法
拒绝水文!八大排序(二)【适合初学者】冒泡排序和选择排序
拒绝水文!八大排序(二)【适合初学者】冒泡排序和选择排序