数据结构——排序算法——基数排序

2023-11-19

基数排序有两种实现方式。本例属于最高位优先法,思路是从最高位开始,依次对基数进行排序。与之对应的是「最低位优先法」,思路是从最低位开始,依次对基数进行排序。
基数排序可以分为以下三个步骤:
1.找到数组中的最大值,确定最大数字的位数
2.从最低位开始,对数组进行计数排序。计数排序是稳定排序,所以在每一位排序后,相同数值的元素仍然保持相对顺序。
3.重复上述步骤,逐渐向更高位进行排序,直到完成所有位的排序。
4.最终,数组中的元素将按照各个位上的数值排序,从而得到有序数组.

基数排序的时间复杂度是 O(nk),其中 n 是数组的元素个数,k 是最大数字的位数。它的时间复杂度通常比较稳定,适用于对整数或字符串进行排序。

// 获取数组中的最大值
int getMax(std::vector<int>& arr) {
    int max = arr[0];
    for (int value : arr) {
        if (value > max) {
            max = value;
        }
    }
    return max;
}

// 基数排序的辅助函数,对数组按照指定位数进行计数排序
void countingSort(std::vector<int>& arr, int exp) {
    int n = arr.size();
    std::vector<int> output(n);
    int counting[10] = {0};

    // 统计当前位数上的数字出现次数
    for (int i = 0; i < n; i++) {
        counting[(arr[i] / exp) % 10]++;
    }

    // 计算累计次数
    for (int i = 1; i < 10; i++) {
        counting[i] += counting[i - 1];
    }

    // 构建排序后的输出数组
    for (int i = n - 1; i >= 0; i--) {
        output[counting[(arr[i] / exp) % 10] - 1] = arr[i];
        counting[(arr[i] / exp) % 10]--;
    }

    // 将排序后的结果复制回原数组
    for (int i = 0; i < n; i++) {
        arr[i] = output[i];
    }
}

// 基数排序函数
void radixSort(std::vector<int>& arr) {
    if (arr.empty()) return;

    int max = getMax(arr);

    // 从最低位到最高位进行排序
    for (int exp = 1; max / exp > 0; exp *= 10) {
        countingSort(arr, exp);
    }
}


对包含负数的数组进行基数排序


// 获取数组中的最大值
int getMax(std::vector<int>& arr) {
    int max = arr[0];
    for (int value : arr) {
        if (value > max) {
            max = value;
        }
    }
    return max;
}

// 基数排序的辅助函数,对非负整数数组按照指定位数进行计数排序
void countingSort(std::vector<int>& arr, int exp) {
    int n = arr.size();
    std::vector<int> output(n);
    int counting[10] = {0};

    // 统计当前位数上的数字出现次数
    for (int i = 0; i < n; i++) {
        counting[(arr[i] / exp) % 10]++;
    }

    // 计算累计次数
    for (int i = 1; i < 10; i++) {
        counting[i] += counting[i - 1];
    }

    // 构建排序后的输出数组
    for (int i = n - 1; i >= 0; i--) {
        output[counting[(arr[i] / exp) % 10] - 1] = arr[i];
        counting[(arr[i] / exp) % 10]--;
    }

    // 将排序后的结果复制回原数组
    for (int i = 0; i < n; i++) {
        arr[i] = output[i];
    }
}

// 基数排序函数,包含对非负和负数的排序
void radixSort(std::vector<int>& arr) {
    if (arr.empty()) return;

    // 分离正数和负数
    std::vector<int> positive;
    std::vector<int> negative;

    for (int num : arr) {
        if (num >= 0) {
            positive.push_back(num);
        } else {
            negative.push_back(-num); // 负数取相反数
        }
    }

    // 对非负整数排序
    if (!positive.empty()) {
        int maxPositive = getMax(positive);
        for (int exp = 1; maxPositive / exp > 0; exp *= 10) {
            countingSort(positive, exp);
        }
    }

    // 对负数排序
    if (!negative.empty()) {
        int maxNegative = getMax(negative);
        for (int exp = 1; maxNegative / exp > 0; exp *= 10) {
            countingSort(negative, exp);
        }
    }

    // 合并正数和负数
    arr.clear();
    arr.insert(arr.end(), negative.rbegin(), negative.rend());
    arr.insert(arr.end(), positive.begin(), positive.end());
}

最高位优先发(MSD)

// 获取数组中的最大值的绝对值
int getMax(std::vector<int>& arr) {
    int max = 0;
    for (int value : arr) {
        if (std::abs(value) > max) {
            max = std::abs(value);
        }
    }
    return max;
}

// 计数排序函数
void countingSort(std::vector<int>& arr, int exp) {
    int n = arr.size();
    std::vector<int> output(n);
    int counting[19] = { 0 };

    // 统计当前位数上的数字出现次数
    for (int i = 0; i < n; i++) {
        int radix = (arr[i] / exp) % 10 + 9; // 转换为正数索引
        counting[radix]++;
    }

    // 计算累计次数
    for (int i = 1; i < 19; i++) {
        counting[i] += counting[i - 1];
    }

    // 构建排序后的输出数组
    for (int i = n - 1; i >= 0; i--) {
        int radix = (arr[i] / exp) % 10 + 9; // 转换为正数索引
        output[--counting[radix]] = arr[i];
    }

    // 将排序后的结果复制回原数组
    std::copy(output.begin(), output.end(), arr.begin());
}

// 最高位优先的基数排序函数,从大到小排序
void radixSortDescending(std::vector<int>& arr, int max) {
    if (arr.empty()) return;

    int exp = 1; // 从最低位开始
    while (max / exp > 0) {
        countingSort(arr, exp);
        exp *= 10;
    }

    // 倒序输出结果,以实现从大到小排序
    std::reverse(arr.begin(), arr.end());
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构——排序算法——基数排序 的相关文章

随机推荐

  • Delphi ListView 的用法

    Delphi ListView 的用法 常用技巧 增加 i ListView1 Items Count with ListView1 do begin ListItem Items Add ListItem Caption IntToStr
  • Vite搭建react+ts项目

    创建一个react项目 首先需要打开终端 进行vite的引入 yarn create vite 使用react模板创建项目 yarn create vite react test template react cd react test y
  • Float与二进制之间的转化(Java实现)

    在线转化 http www binaryconvert com 2 3 import java text DecimalFormat 4 5 6 public class SinglePrecision 7 8 浮点到二进制 9 publi
  • 采用通信方式控制台达B2伺服驱动器运行在速度模式

    目录 前言 一 伺服驱动器恢复出厂设置 二 伺服驱动器设置为速度模式 三 关闭告警信息 四 通讯功能设置 五 采用通信功能控制伺服驱动器按速度模式运行 总结 前言 最近 使用台达B2伺服驱动器做项目 项目中用伺服电机的速度模式驱动一个螺杆按
  • Linux笔记--查看Linux系统自动Kill掉的进程

    目录 1 前言 2 查看系统日志 3 参考 1 前言 今天在服务器训练一个模型 程序无任何错误 但一段时间后挂在后台的进程莫名被Kill掉 原因在于服务器 linux 系统的运行内存不足 为了避免系统奔溃 系统主动 kill 内存占用最大的
  • Python项目创建(Pycharm程序)

    点击 新建项目 创建一个新的项目 这一步重点在Python解释器的选择 一个是新建虚拟环境 另一个是使用已有环境 使用此工具新建环境 Virtualenv 新建后在项目根目录下会出现 venv 的文件夹 相当于把Python解释器复制过去一
  • RANSAC算法实现 + 直线拟合

    一 RANSAC算法 1 参考资料 1 题目来源与解析 商汤科技SLAM算法岗的RANSAC编程题 2 牛客网题目 编程题 线性回归 3 牛客网解答参考 商汤科技某算法岗的编程题有点过分了啊 4 RANSAC算法原理 RANSAC翻译 经典
  • TOPIAM 社区版 1.0.0 发布,开源 IAM/IDaaS 企业身份管理平台

    文章目录 产品概述 系统架构 功能列表 管理端 门户端 技术架构 后续规划 相关地址 Hi 亲爱的朋友们 今天是传统 24 节气中的立秋 秋天是禾谷成熟 收获的季节 经过长时间优化和迭代 TOPIAM 企业身份管控平台也迎来了当下的成长和收
  • [Redis]-四种部署方式

    森格 2022年11月 本文是对Redis部署方式的学习 主要学习基本原理 以及几种方式的优缺点 一 部署方式概况 对于Redis的安装部署主要可以分为单机版 主从同步 Sentinel哨兵 Cluster集群部署四种方式 下面一起看下几种
  • AutoCAD 2022 for Mac v2022(24.1.50.899)中文版介绍

    CAD2022 Mac是一款针对苹果电脑打造的CAD设计软件 用于二维绘图 详细绘制 设计文档和基本三维设计 广泛应用于机械设计 工业制图 工程制图 土木建筑 装饰装潢 服装加工等多个行业领域 CAD2022新特征 改进了桌面 Web和移动
  • 一个全网最详细的Python教程,不信你来学一学!2023Python入门教程完整版,无偿分享

    近几年 编程越来越火 网上也是铺天盖地的免费教程 中小学生都开始投入到学习中 编程学习从娃娃抓起 甚至有些小学生都做起了 UP 主 教大家学编程 PS 我落下了柠檬的眼泪 小小年纪就学得一手好编程 光从编程的难易度来说 Python 简单
  • IDEA进行了Pull操作,Merge时选择了他们的优先,但自己的代码没有Push导致自己未提交的代码没了,头脑发热我差点哭出来解决方案

    IDEA进行了Pull操作 Merge时选择了他们的优先 但自己的代码没有Push导致自己未提交的代码没了 头脑发热我差点哭出来解决方案 问题背景 解决方案 心得 Lyric 沉默是因为包容 问题背景 我和胖哥同时在一个项目里面开发 我让他
  • 华为OD机试 - 判断字符串子序列(Java)

    题目描述 给定字符串 target和 source 判断 target是否为 source 的子序列 你可以认为target和 source 中仅包含英文小写字母 字符串 source 可能会很长 长度 500 000 而 target是个
  • python笔记(爬虫 微爬取微信信息)

    views py import time import json import re import requests from bs4 import BeautifulSoup from flask import Blueprint ren
  • DevExpress ASP.NET GridView在Edit时弹出新窗体

    1 设置setting editing属性 选择PopupEditForm 2 如果在源代码中设置的话 如下
  • 机器学习入门教学——梯度下降、梯度上升

    1 简介 梯度表示某一函数在该点处的方向导数沿着该方向取得最大值 即函数在该点处沿着该方向 梯度的方向 变化最快 变化率 梯度的模 最大 可理解为导数 梯度上升和梯度下降是优化算法中常用的两种方法 主要目的是通过迭代找到目标函数的最大值和最
  • 编译原理实验一(C-语言词法分析器的编写C语言版本)

    编译原理实验一 C 语言词法分析器的编写C语言版本 一 tiny词法分析程序源代码阅读笔记 重要变量和函数 变量和函数 A 要计算的唯一特性是词法或是被识别的记号的串值 变量t o k e n S t r i n g B 扫描程序使用3个全
  • 设计模式:观察者模式

    观察者模式 又被称为发布 订阅 Publish Subscribe 模式 属于行为型模式的一种 它定义了一种一对多的依赖关系 让多个观察者对象同时监听某一个主题对象 这个主题对象在状态变化时 会通知所有的观察者对象 使他们能够自动更新自己
  • github-render.s3.amazonaws.com 报错 The specified key does not exist.

    GitHub网站在浏览 ipynb 类型的文件的时候 需要调用 https github render s3 amazonaws com 下面的接口 结果一直报404错误 返回的 xml 里面信息是 The specified key do
  • 数据结构——排序算法——基数排序

    基数排序有两种实现方式 本例属于最高位优先法 思路是从最高位开始 依次对基数进行排序 与之对应的是 最低位优先法 思路是从最低位开始 依次对基数进行排序 基数排序可以分为以下三个步骤 1 找到数组中的最大值 确定最大数字的位数 2 从最低位