模仿qsort实现一个冒泡排序的通用算法

简介: 在一些编程题中经常需要你按照某个指标按照从小到大或从大到小输出一些数据,这时你可以自己写一个排序函数进行排序,但是其实C语言函数库中就有一个排序函数--qsort函数,使用它可以节省你单独写排序函数所耗费的时间,因而在一些比赛中广泛应用
  1. :boom:qsort函数介绍
  2. :boom:冒泡排序介绍
  3. :boom:什么是冒泡排序的通用算法
  4. :boom:模仿qsort的一个冒泡排序的通用算法
  5. :boom:结语

在这里插入图片描述


1.qsort函数介绍

在一些编程题中经常需要你按照某个指标按照从小到大或从大到小输出一些数据,这时你可以自己写一个排序函数进行排序,但是其实C语言函数库中就有一个排序函数--qsort函数,使用它可以节省你单独写排序函数所耗费的时间,因而在一些比赛中广泛应用。

==qsort函数用白一点的话来讲就是可以排任何类型的数,不仅仅局限于整形==

==它要用到的头文件<stdilb.h>==
下面是它的函数参数介绍:triangular_flag_on_post:

void qsort ( void * base,     //base:参与排序的数组指针
            size_t num,     //num:参与排序的元素个数;
            size_t size,     //size:单个元素的大小;
            int ( * comparator ) ( const void *, const void * ) )
            //( * comparator ) ( const void *, const void * ):比较函数指针;
*base:参与排序的数组指针;
num:参与排序的元素个数;
size:单个元素的大小,单位是字节;
( comparator ) ( const void , const void ):比较函数指针(程序员自己定义);**

---

我们来一个实际列子使用一下==qsort函数==>>

#include<stdio.h>
#include<stdlib.h>
struct Stu
{
    char name[20];
    int age;
};

int sort_by_age(const void* e1, const void* e2)//用来比较age大小的函数,这里就相当于qsort中的比较函数
{
    //如果age1>age2就返回大于零,相等就返回零,小于就返回小于零的数即可
    return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int main()
{
    //使用qsort函数排序结构体数据
    struct Stu s[3] = { {"zhangsan", 30},{"lisi", 34},{"wangwu", 20} };
    int sz = sizeof(s) / sizeof(s[0]);
    //按照年龄来排序
    qsort(s, sz, sizeof(s[0]), sort_by_age);
    for (int i = 0; i < 3; i++)
    {
        printf(" %s %d  \n",s[i].name, s[i].age);
    }
    return 0;
}

运行后的结果>

在这里插入图片描述
当然如果你想用名字排名也可以,只需把这个比较函数传给qsort即可

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

2.冒泡排序介绍
冒泡排序的原理是:从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。

以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。

它的时间复杂度是o(N^2)
假如有一个数组为(21435)
image.png

冒泡排序.gif

这个也比较简单我就直接上代码了>>


void BBsort(int arr[], int size)
{
    int j,i,tem;
    for (i = 0; i < size-1;i ++)//size-1是因为不用与自己比较,所以比的数就少一个
    {
        int count = 0;
        for (j = 0; j < size-1 - i; j++)    //size-1-i是因为每一趟就会少一个数比较
        {
            if (arr[j] > arr[j+1])//这是升序排法,前一个数和后一个数比较,如果前数大则与后一个数换位置
            {
                tem = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tem;
                count = 1;
                
            }
        }
        if (count == 0)            //如果某一趟没有交换位置,则说明已经排好序,直接退出循环
                break;    
    }

3. 什么是冒泡排序的通用算法
简而言之,通用算法就是适用于一般数据的排序,也就是说我们上面这个冒泡排序只能用来排序整形的数,而我们的通用冒泡排序就是模仿qsort函数一样可以用来排序任意数据。:thought_balloon:
我们实现的这个冒泡排序通用算法区别于C语言函数库中的qsort在于qsort同的是快速排序思想,而我们用的是冒泡排序思想。

4. 模仿qsort的一个冒泡排序的通用算法

⭐️首先我们要想qsort为什么能排序任意类型的数据?
:sparkles:我们从它的函数参数或许可以知道些许qsort

void qsort ( void * base,     //base:参与排序的数组指针
            size_t num,     //num:参与排序的元素个数;
            size_t size,     //size:单个元素的大小;
            int ( * comparator ) ( const void *, const void * ) )
    //( * comparator ) ( const void *, const void * ):比较函数指针;

🐾这里就直接代码展示>>


//qsore函数使用
//模仿qsort实现一个冒泡排序的通用算法
#include<stdio.h>
#include<stdlib.h>
void Swap(char* buff1, char* buff2, int width);//交换元素的函数声明
//base数组首地址,sz数组元素长度,width元素占多少个字节,cmp元素比较的方式的函数,元素相等return 0,大于return 大于零的数,小于则return小于零的数
void bubble_sort(void *base,int sz,int width,int (*cmp)(const void* e1,const void* e2))
{
    int i, j;
    for (i = 0; i < sz; i++)
    {    //一趟的排序
        for (j = 0; j < sz - i - 1; 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(const void* e1,const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}
int main()
{
    int arr[] = { 1,3,4,2,6,5,7,8,9,10 };
    qsort(arr, sizeof(arr) / sizeof(arr[0]), 4, cmp);
    //bubble_sort(arr, sizeof(arr) / sizeof(arr[0]), 4, cmp);
    
    for (int j = 0; j < 10; j++)
    {
        printf("%d ", arr[j]);
    }
    
    return 0;
}
void Swap(char* buff1, char* buff2, int width)//交换元素的函数
{
    int i;
    for (i = 0; i < width; i++)
    {
        char tem = *buff1;
        *buff1 = *buff2;
        *buff2 = tem;
        buff1++;
        buff2++;
    }
}

==这些是我从上面拿出来重点要跟大家说明的==

        void*base

==☁️首先为什么是void 类型,可能有些小伙伴不知道void 的用法,我这里简单说一下,void 确实它跟int char 等等都是指针,而像int 这些是只能接收一下int 类型的指针,void 就不一样了,它可以接收所有的指针类型==
这就很好的解释了为什么要用void 来作为函数参数了,因为我们是要排序任意类型的数据,所以一定要用void 来接收


比较一下通用冒泡排序和一般冒泡排序的判断元素大小

if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
if (arr[j] > arr[j+1])//一般的冒泡排序
☁️而这里就体现了为什么要传每一个元素的大小了,因为是接收任意类型的数据,所以我们需要通过每一元素的大小来确定该用多少字节来进行比较和元素交换,而且这里base要强制类型转换,因为void*
是不能直接访问的,我们把它按char*来处理后,就很容易跟后面传进来的“width”元素大小进行匹配

....
//交换
Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);
        ......
void Swap(char* buff1, char* buff2, int width)//交换元素的函数
{
    int i;
    for (i = 0; i < width; i++)
    {
        char tem = *buff1;
        *buff1 = *buff2;
        *buff2 = tem;
        buff1++;
        buff2++;
    }
}

☁️这是一个交换函数,这里可以是void 接收,也可以提前将base强制类型转换成char 然后再传,我这就是后者。这我要跟大家说的就是为什么要传“width”元素大小,因为跟前面一样,我们知道了元素大小才能知道要交换多少个元素




在这里插入图片描述


相关文章
|
1天前
|
搜索推荐 算法 Python
python实现冒泡排序算法
python实现冒泡排序算法
27 0
|
1天前
|
搜索推荐 算法 Java
sort-01-bubble sort 冒泡排序算法详解
这是一个关于排序算法的系列文章摘要。作者整理了10种不同的排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序和大文件外部排序。文章详细介绍了冒泡排序的工作原理、流程,并提供了代码实现,强调了在实现中考虑的改进点,如统一接口、实用性增强和日志输出。此外,还提供了一个排序接口和工具类以方便使用,并通过测试代码和日志展示了排序过程。整个系列旨在帮助读者理解和掌握排序算法。相关代码已开源在GitHub。
|
1天前
|
存储 算法 搜索推荐
【数据结构与算法】归并排序(详解:递归与非递归的归并排序 | 赠:冒泡排序和选择排序)
【数据结构与算法】归并排序(详解:递归与非递归的归并排序 | 赠:冒泡排序和选择排序)
|
1天前
|
搜索推荐 算法 Java
Java基础(冒泡排序算法)
Java基础(冒泡排序算法)
19 3
|
1天前
|
搜索推荐 算法 C语言
C语言实现冒泡排序算法
C语言实现冒泡排序算法
19 0
|
1天前
|
搜索推荐 C#
C#实现冒泡排序算法
C#实现冒泡排序算法
20 0
|
1天前
|
搜索推荐 Python
Python 实现冒泡排序算法
Python 实现冒泡排序算法
11 0
|
1天前
|
搜索推荐 算法
在冒泡排序算法中,为什么每次比较相邻的元素时都要进行交换?
【2月更文挑战第8天】【2月更文挑战第21篇】在冒泡排序算法中,为什么每次比较相邻的元素时都要进行交换?
|
1天前
|
搜索推荐 Python
python实现冒泡排序算法。
【2月更文挑战第8天】【2月更文挑战第20篇】python实现冒泡排序算法。
|
1天前
|
存储 搜索推荐 算法
【数据结构排序算法篇】----冒泡排序【实战演练】
【数据结构排序算法篇】----冒泡排序【实战演练】
29 2

热门文章

最新文章