常用排序算法的实现与介绍

news2024/9/25 23:24:59

常用排序算法的实现与介绍

在这里插入图片描述

在计算机科学中,排序算法是非常基础且重要的一类算法。本文将通过C语言代码实现,介绍几种常见的排序算法,包括冒泡排序、选择排序、插入排序和快速排序。以下是这些排序算法的具体实现和简要介绍。

1. 冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法,它重复地走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。这个过程会重复进行直到没有元素需要交换为止。

void bupsort(TYPE *arr, size_t len) {
    bool flag = true; // 标记是否发生交换
    for (size_t i = len - 1; i > 0 && flag; i--) {
        flag = false;
        for (size_t j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(&arr[j], &arr[j + 1]);
                flag = true; // 发生交换
            }
        }
    }
    printf("%s\n", __func__);
}
2. 选择排序(Selection Sort)

选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

void select_sort(TYPE *arr, size_t len) {
    for (size_t i = 0; i < len - 1; i++) {
        size_t min_index = i;
        for (size_t j = i + 1; j < len; j++) {
            if (arr[j] < arr[min_index]) {
                min_index = j;
            }
        }
        if (min_index != i) {
            swap(&arr[i], &arr[min_index]);
        }
    }
    printf("%s\n", __func__);
}
3. 插入排序(Insertion Sort)

插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

void insert_sort(TYPE *arr, size_t len) {
    for (size_t i = 1, j = 0; i < len; i++) {
        TYPE key = arr[i];
        for (j = i - 1; j >= 0 && arr[j] > key; j--) {
            arr[j + 1] = arr[j];
        }
        arr[j + 1] = key;
    }
    printf("%s\n", __func__);
}
4. 快速排序(Quick Sort)

快速排序是一种分治法的排序算法。它通过选择一个基准元素,将待排序数组分割成两部分,递归地排序两个子数组。

// 处理分区逻辑的函数
int _Qsort(int *arr, int low, int high) {
    int pivot = arr[high];
    int index = low - 1;

    for (int i = low; i < high; i++) {
        if (arr[i] < pivot) {
            index++;
            swap(&arr[i], &arr[index]);
        }
    }

    swap(&arr[index + 1], &arr[high]);
    return index + 1;
}

// 递归调用函数
void _Qsort_recursive(int *arr, int low, int high) {
    if (low < high) {
        int pi = _Qsort(arr, low, high);

        _Qsort_recursive(arr, low, pi - 1);
        _Qsort_recursive(arr, pi + 1, high);
    }
}

// 公共接口函数
void Qsort(int *arr, size_t len) {
    if (arr != NULL && len > 0) {
        _Qsort_recursive(arr, 0, len - 1);
    }
    printf("%s\n", __func__);
}
5.希尔排序(shell sort)
//希尔排序
void shell_sort(TYPE *arr, size_t len) 
{
    for(int gap = len / 2; gap > 0; gap /= 2)
    {
        for(int i = gap,j=0; i < len; i++)
        {
            TYPE key = arr[i];
            for(j = i; j-gap >= 0 && arr[j-gap] > key; j -= gap)
            {
                arr[j] = arr[j-gap];
            }
            if(i != j)
            arr[j] = key;
        }
    }
printf("%s\n",__func__);
}

主函数和测试

在主函数中,我们使用一个函数数组分别调用以上几种排序算法,并对随机生成的数组进行排序。

int main() {
    TYPE arr[LEN];
    sort_func sorts[] = {bupsort, Qsort, select_sort, insert_sort};

    for (int i = 0; i < sizeof(sorts) / sizeof(sorts[0]); i++) {
        for (int j = 0; j < LEN; j++) {
            arr[j] = rand() % 100; // 填充数组随机值
        }
        printf("排序前: ");
        show_arr(arr, LEN);

        sorts[i](arr, LEN); // 调用排序函数

        printf("排序后: ");
        show_arr(arr, LEN);
        printf("==========================\n");
        printf("\n");
    }

    return 0;
}

在这个例子中,我们展示了如何使用C语言实现几种常见的排序算法,并通过函数指针数组动态调用不同的排序函数。通过这样的实现方式,可以方便地扩展和测试不同的排序算法。希望本文能帮助读者更好地理解和掌握这些基础的排序算法。

完整代码:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#define TYPE int
#define LEN 15

void swap(int *a, int *b) 
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
void show_arr(TYPE *arr,size_t len)
{
    for(size_t i=0;i<len;i++)
    {
        printf("%d ",arr[i]);
    }
    printf("\n");
}
typedef void (*sort_func)(TYPE *arr,size_t len);// 排序函数类型定义

//冒泡排序
void bupsort(TYPE *arr,size_t len)
{
    bool flag=true;// 标记是否发生交换
    for(size_t i=len-1;i>0&&flag;i--)//发生过交换才继续
    {
        flag=false;// 标记是否发生交换
        for(size_t j=0;j<i;j++)
        {
            if(arr[j]>arr[j+1])
            {
                swap(&arr[j],&arr[j+1]);
                flag=true;// 发生交换
            }
        }
    }
    printf("%s\n",__func__);
}


//选择排序
void select_sort(TYPE *arr, size_t len) {
    for (size_t i = 0; i < len - 1; i++) {
        size_t min_index = i;
        for (size_t j = i + 1; j < len; j++) {
            if (arr[j] < arr[min_index]) {
                min_index = j;
            }
        }
        if (min_index != i) {
            swap(&arr[i], &arr[min_index]);
        }
    }
    printf("%s\n",__func__);
}

//插入排序
void insert_sort(TYPE *arr, size_t len) 
{
    for (size_t i = 1,j=0; i < len; i++) 
    {
        TYPE key = arr[i];
        for( j = i - 1; j >= 0 && arr[j] > key; j--)
        {
            arr[j+1] = arr[j];
        }
        arr[j+1] = key;
    }
    printf("%s\n",__func__);
}

//快速排序
// 处理分区逻辑的函数
int _Qsort(int *arr, int low, int high) {
    int pivot = arr[high]; // 最后一个元素作为基准
    int index = low - 1; // 记录小于基准元素的位置

    for (int i = low; i < high; i++) {
        if (arr[i] < pivot) {
            index++;
            swap(&arr[i], &arr[index]); // 将小于基准的元素移到左边
        }
    }

    swap(&arr[index + 1], &arr[high]); // 将基准元素放到中间
    return index + 1;
}

// 递归调用函数
void _Qsort_recursive(int *arr, int low, int high) {
    if (low < high) {
        int pi = _Qsort(arr, low, high);

        _Qsort_recursive(arr, low, pi - 1); // 排序左半部分
        _Qsort_recursive(arr, pi + 1, high); // 排序右半部分
    }
}

// 公共接口函数
void Qsort(int *arr, size_t len) {
    if (arr != NULL && len > 0) {
        _Qsort_recursive(arr, 0, len - 1);
    }
    printf("%s\n",__func__);
}
int main() {
    TYPE arr[LEN];
    sort_func sorts[] = {bupsort, Qsort, select_sort , insert_sort};// 排序函数数组

    for (int i = 0; i < sizeof(sorts) / sizeof(sorts[0]); i++) {
        for (int j = 0; j < LEN; j++) {
            arr[j] = rand() % 100; // 填充数组随机值
        }
        printf("排序前: ");
        show_arr(arr, LEN);

        sorts[i](arr, LEN); // 调用排序函数

        printf("排序后: ");
        show_arr(arr, LEN);
        printf("==========================\n");
        printf("\n");
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1971091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis 进阶】主从复制(重点理解流程和原理)

在分布式系统中为了解决单点问题&#xff08;某个服务器程序只有一个节点&#xff08;只搞一个物理服务器来部署这个服务器程序&#xff09;。可用性不高&#xff1a;如果这个机器挂了意味着服务就中断了&#xff1b;性能 / 支持的并发量比较有限&#xff09;。通常会把数据复制…

免费插件集-illustrator插件-Ai插件-黄金比率绘图

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;绘制黄金比率示意图。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/87890501&am…

【ESP32接入国产大模型之星火】

【ESP32接入国产大模型之星火】 1. 讯飞星火大模型1.1 了解星火 api1.2 Http接口鉴权1.3 http调用1.3.1 http请求结构体1.3.2 返回(response)参数1.3.3 错误响应 2. 先决条件2.1 环境配置2.2 所需零件 3. 核心代码3.1 源码分享3.2 源码解析 4. 上传验证4.1 对话测试4.2 报错 5.…

【MySQL】一文彻底吃透MVCC执行原理

1.MVCC是什么&#xff1f; MVCC全称Multi-Version Concurrency Control&#xff0c;即多版本并发控制。它通过维护数据的多个版本来实现高效的并发控制&#xff0c;用于在多个并发事务同时读写数据库时保持数据的一致性和隔离性。 在搞清楚MVCC的实现原理之前&#xff0c;还需…

一天攻克一个知识点 —— 设计模式之动态代理

一、设计模式之代理设计 代理设计是在Java开发中使用较多的一种设计模式&#xff0c;所谓的代理设计模式就是指一个代理主体操作真实主体&#xff0c;真实主体操作具体业务&#xff0c;代理主体负责给具体业务添砖加瓦。 就好比在生活中你有一套房子想要出租(你真实主体)&…

Mysql-窗口函数一

文章目录 1. 窗口函数概述1.1 介绍1.2 作用 2. 场景说明2.1 准备工作2.2 场景说明2.3 分析2.4 实现2.4.1 非窗口函数方式实现2.4.2 窗口函数方式实现 3. 窗口函数分类4. 窗口函数基础用法&#xff1a;OVER关键字4.1 语法4.2 场景一 :计算每个值和整体平均值的差值4.2.1 需求4.2…

免费的远程办公软件

产生背景 我们的SD-WAN组网的产品一直都是以CPE盒子的形式进行交付&#xff0c;如果您有多个企业分支&#xff0c;那么需要在每个分支安装一个CPE盒子。 这种形式存在一些问题&#xff1a; 成本过高&#xff0c;CPE盒子本身是有成本的&#xff0c;没办法做到免费使用&#xf…

用Maven构建项目和管理依赖

运行本篇中的代码&#xff1a;idea专业版或者idea社区版本&#xff08;2021.1~2022.1.4&#xff09; 用Maven构建项目和管理依赖 1. 初见maven2. maven在网站项目中的应用3. maven和idea的关系4. maven的使用4.1 项目构建4.11 在idea创建maven项目4.12 利用maven命令打包项目 4…

“QtGraphicalEffects“ is not installed

【1】问题&#xff1a;qml项目报 module "QtGraphicalEffects" is not installed 【2】解决方法&#xff1a;将qml目录中的"QtGraphicalEffects" 拷贝到工程release目录

3种 Ajax 方式:原生、jQuery、axios

毋庸多言&#xff0c;Ajax 技术在网页中是划时代的进步。学会它&#xff0c;可以说掌握了一招半式&#xff0c;不再是门外汉了。 这里将 3 种 Ajax 方式一并呈上。 感谢 https://run.uv.cc/ 平台&#xff0c;以及 /api 接口 https://andi.cn/page/621639.html https://andi…

用Java手写jvm之模拟类加载器加载class

写在前面 本文来尝试模拟类加载器加载class的过程。 1&#xff1a;程序 首先来定义类加载器类&#xff1a; /*** 类加载器* 正常应该有bootstrap&#xff0c;ext&#xff0c;app三个类加载器&#xff0c;这里简单起见&#xff0c;只用一个来模拟了*/ public class ClassLoa…

入门 PyQt6 看过来(案例)20~ 动态树

​ 1 QTreeWidget树类 QTreeWidget类可以呈现数组、数列等数据&#xff0c;并且可以进行交互&#xff0c;它使用标准的数据模型&#xff0c;其单元格数据通过QTableWidgetItem对象来实现。 QTreeWidget继承自QTreeView&#xff0c;是封装了默认Model的QTreeView&#xff0c;其…

C++ | Leetcode C++题解之第312题戳气球

题目&#xff1a; 题解&#xff1a; class Solution { public:int maxCoins(vector<int>& nums) {int n nums.size();vector<vector<int>> rec(n 2, vector<int>(n 2));vector<int> val(n 2);val[0] val[n 1] 1;for (int i 1; i &l…

ElasticSearch入门(六)SpringBoot2

private String author; Field(name “word_count”, type FieldType.Integer) private Integer wordCount; /** Jackson日期时间序列化问题&#xff1a; Cannot deserialize value of type java.time.LocalDateTime from String “2020-06-04 15:07:54”: Failed to des…

Django文件上传

【图书介绍】《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 本节主要介…

【计算机网络】IP地址和子网掩码(子网掩码篇)

个人主页:【😊个人主页】 系列专栏:【❤️计算机网络】 文章目录 前言什么是子网掩码?子网掩码的组成组成规则表示方法子网掩码的分类标准(默认)子网掩码:变长子网掩码(VLSM):全零和全一子网掩码:子网掩码的计算确定IP地址类别及默认子网掩码计算子网掩码根据子网数…

橙单中台化低代码生成器

​橙单中台化低代码生成器 在当今快速发展的软件开发领域&#xff0c;橙单中台化低代码生成器凭借其强大的功能和灵活的架构&#xff0c;成为了开发者不可或缺的利器。本文将介绍橙单的基本信息、特点以及如何快速部署和使用。 软件简介 橙单中台化低代码生成器是一款开源的低…

被华为的AI扩图震惊到,超自然超好看!

美颜、P图对大家来说都不陌生&#xff0c;但是近期在互联网实火的各种AI扩图你了解多少&#xff1f;它既能满足图片构图时进行延伸美化&#xff0c;又能在未知的创意里无限探索。 近期&#xff0c;华为Pura 70系列手机获推HarmonyOS 4.2.0.172 更新&#xff0c;华为Pura 70 Pr…

事务性邮件API的功能优势?考虑哪些指标?

事务性邮件API的性能如何优化&#xff1f;怎么选择邮件API接口&#xff1f; 在当今数字化时代&#xff0c;企业需要一种高效、可靠的方法与客户沟通。事务性邮件API成为解决这一需求的重要工具。AokSend将探讨事务性邮件API的功能优势及考虑的关键指标。 事务性邮件API&#…

如何在 Kubernetes 中使用 ClickHouse 和 JuiceFS

ClickHouse 结合 JuiceFS 一直是一个热门的组合&#xff0c;社区中有多篇实践案例。今天的文章来自美国公司 Altinity&#xff0c;一家提供 ClickHouse 商业服务的企业&#xff0c;作者是 Vitaliy Zakaznikov&#xff0c;他尝试了这个组合并公开了过程中使用的代码。原文有两篇…