字符串 - 字符串排序

2023-05-16

1. 字符串排序

对于许多排序应用来说,决定顺序的键都是字符串。给定一列字符串,需要按一定顺序排列整齐方便后序处理。

2.  键索引计数法

这个方法名字有点拗口,过程有点绕,但是每一步其实很简单。

举个简单的例子:

 

 

 

过程看着有点复杂,但是代码真的非常简单,一步一行就可以。


    public static void string_count(String[] a, int R)
    {
        int N = a.length;
        int[] Count = new int[R+1];
        String[] aux = new String[N];

        for(int i=0;i<N;i++)
            Count[a[i].key()+1]++; //计数
        for(int i=0;i<R;i++)
            Count[i+1] += Count[i]; //Count数组向前累加
        for(int i=0;i<N;i++)
            aux[Count[a[i].key()]++] = a[i];  //将元素分类
        
        for(int i=0;i<N;i++)
            a[i] = aux[i];  //回写
    }  

这里a[i].key()表示字符串a[i]的键,我们按照键对数组a进行排序,也就是说键小的在前,键大的在后。

 注意这里一定要理解清楚,键索引计数法是后面两种算法的基础。

而且键索引计数法是稳定的,也就是说,同一个键的话,字符串的相对顺序不会改变。

 

3. 低位优先的字符串排序

位优先的字符串排序方法适合数组中所有字符串的长度相等的情况。

例如 String a[]= {"ao01", "adf5", "erh4","6te5"},字符串数组a中所有的字符串都是4位。

这种情况就可以用低位优先的字符串排序,具体来说就是从最末尾一位开始排序,排完了之后,再按照倒数第二位开始排序,直到第一个字符。一共要经历四轮排序,最后得到最终顺序。

我一开始看的时候也是好奇为什么要从最后一位开始比,然后再依次比到第一位。包括自己也拿程序验证了一下,如果是从第一位先排,再排到最后一位结果确实是不对的。

但是仔细想了一下,这个过程其实就类似于数字的比大小。以四位数为例,先从千位开始比,从小到大排好,再按百位排,就相当于打乱了这一顺序,得出来的排序没有任何意义,因为千位的排序本身是要比百位更重要的。相反,假如从个位开始排,那么个位数大的排在后面,然后再排十位,打乱的话,这个过程是有意义的。因为十位本身就决定了排序,而假如十位相同的话,那么第一轮决定了个位数大的排在后面。这个时候就真正实现了数字的排序。同理也可以应用于字符串的排序。

这个算法的核心在于排序次数线性正比于字符串长度。假如字符串长度均为n,那么就只需要操作n次。并且原地排序不需要占用任何其他内存。这样看这个算法其实是简洁且快速的。


public class LSD
{
    public static void sort(String[] a, int W) //W为字符串的长度
    {
        int N = a.length;
        int R = 256; //字典大小;

        String[] aux = new String[N];

        for(int d=W-1;d>=0;d--)
        {
            int[] Count = new int[R+1]; //注意这一行是在循环里面,因为每一轮循环都有自己独立的count数组
            
            for(int i=0;i<N;i++)
                Count[a[i].charAt(d)+1]++;  //计算次数

            for(int i=0;i<R;i++)
                Count[i+1] += Count[i]; //Count向前累加

            for(int i=0;i<N;i++)
                aux[Count[a[i].charAt(d)]++] = a[i];

            for(int i=0;i<N;i++)
                a[i] = aux[i]; // 回写
        }
    }

    public static void main(String[] args) 
    {
        String[] a = {"4ADC","4BPL","0HPD","0BME"};
        int W = 4;
        sort(a, 4);
        for(int i=0;i<4;i++)
        {
            System.out.println(a[i]);
        }

    }
}

输出结果为 

 

4. 高位优先字符串

高位优先字符串则更加通用一些,可以处理一个字符串数组中,字符长度不定的情况。

具体方法为,先用键索引计数法将所有字符串按照首字母排序,然后递归的将每个首字母所对应的子数组排序。如果遇到["A", "AB"],具有相同前缀,但有些字符串已经结束,另一些没结束,则把已经结束了的放在子字符串数组的前面。


public class MSD {
    private static int R = 256;
    private static String[] aux;


    private static int charAt(String s, int d)
    {
        if(d>=s.length()) return -1;
        else return s.charAt(d);
    }

    public static void sort(String[] a)
    {
        int N = a.length;
        aux = new String[N];
        sort(a, 0, N-1, 0);
    }
    
    //a为带排序数组,lo开始考虑的位置,hi考虑的最后一个字符串的位置,考虑的第d位字符
    public static void sort(String[] a, int lo, int hi, int d)
    {
        if(lo>=hi)
            return;
        int[] Count = new int[R+2];
        for(int i=lo;i<=hi;i++)           //计算频率
            Count[charAt(a[i], d) + 2]++;
        
        for(int r=0;r<R+1;r++)          //将频率转化为索引
            Count[r+1] += Count[r];

        for(int i=lo; i<=hi;i++)        //数据分类
            aux[Count[charAt(a[i], d)+1]++] = a[i];
        for(int i=lo;i<=hi;i++)       //回写
            a[i] = aux[i-lo]; 

        for(int r=0;r<R;r++)  //递归以每个字符为键进行排序
            sort(a, lo + Count[r], lo + Count[r+1]-1, d+1);
    }

    public static void main(String[] args)
    {
        String[] a = {"4ADC","4BPL","0HPD","0BME"};
        sort(a);
        for(int i=0;i<4;i++)
        {
            System.out.println(a[i]);
        }

    }
}  

 

用同样的测试数据,得到了和低位优先排序一样的结果。

 

5. 三向字符串快速排序

三向指的是每次排序都只把数组切分位三部分。这样可以提高每次排序的效率,避免每次都要生成一堆空子数组。

三向字符串快速排序特别适合有特别长的公共前缀的字符串

 


public class Quick3string {
    private static int charAt(String s, int d) {
        if (d >= s.length()) return -1;
        else return s.charAt(d);
    }

    public static void sort(String[] a) {
        sort(a, 0, a.length - 1, 0);
    }

    public static void sort(String[] a, int lo, int hi, int d) {
        if (lo >= hi) return;
        int lt = lo, gt = hi;
        int v = charAt(a[lo], d);
        int i = lo + 1;
        while (i <= gt) {
            int t = charAt(a[i], d);
            if (t < v) exch(a, lt++, i++);
            else if (t > v) exch(a, i, gt--);
            else i++;
        }
        sort(a, lo, lt - 1, d); //先把小于首字母的部分按首字母再继续递归排序
        if (v >= 0) sort(a, lt, gt, d + 1); //把等于首字母的,且还没有遍历完成的就排后一个字母
        sort(a, gt + 1, hi, d); //大于首字母的也是继续按首字母再继续递归排序
    }

}  

 

转载于:https://www.cnblogs.com/corineru/p/10799686.html

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

字符串 - 字符串排序 的相关文章

  • ntoj 808 蚂蚁的难题(八)

    蚂蚁的难题 八 时间限制 xff1a 2000 ms 内存限制 xff1a 65535 KB 难度 xff1a 5 描述 蚂蚁是一个古玩爱好者 xff0c 他收藏了很多瓶瓶罐罐 有一天 xff0c 他要将他的宝贝们一字排开 xff0c 摆放
  • CentOS 7尝试安装 phpstudy

    安装方法 xff08 phpstudy for linux V0 2公测版 xff09 使用 SSH 连接工具 连接到您的 Linux服务器后 xff0c 根据系统执行相应命令开始安装 xff08 大约2分钟完成面板安装 xff09 xff
  • asp.net 2.0中傻瓜式使用soap header

    在websevrice 中 soap header是十分重要的哦 xff0c 主要是安全性的考虑 xff0c 在asp net 2 0中 可以简单地应用soap header来 进行傻瓜式的应用 xff0c 更复杂的应用当然要更深入地去看了
  • Linux操作系统中对于NTFS读取目录功能的实现

    1 2 We use the same basic approach as the old NTFS driver i e we parse the 3 index root entries and then the index alloc
  • matlab练习程序(演化策略ES)

    还是这本书上的内容 xff0c 不过我看演化计算这一章是倒着看的 xff0c 这里练习的算法正好和书中介绍的顺序是相反的 演化策略是最古老的的演化算法之一 xff0c 和上一篇DE算法类似 xff0c 都是基于种群的随机演化产生最优解的算法
  • 火狐浏览器无法打开

    解决火狐浏览器无法打开的问题 xff1a 第一种方法 请先检查一下任务管理器中有没有火狐的进程 xff08 firefox exe xff09 xff0c 有的话 xff0c 请在任务管理器中强行关闭它 xff0c 然后试试用safe mo
  • 快上车项目简介(500字)

    第8组 快上车 xff0c 这是一款日常生活中非常有趣的安卓手机软件 xff0c 致力于打造一个大学生的专属娱乐创意社区 xff0c 讨论的话题轻松休闲贴近大学生活 xff0c 与在社会中十分流行的贴吧 xff0c 糗事百科类似 在快上车中
  • 挂载硬盘,提示 mount: unknown filesystem type 'LVM2_member'的解决方案

    问题现象 xff1a 由于重装linux xff0c 并且加了固态硬盘 xff0c 直接将系统装在固态硬盘中 启动服务器的时候 xff0c 便看不到原来机械硬盘的挂载目录了 xff0c 不知如何访问机械硬盘了 直接用命令 mount dev
  • 对目前市面上WPF书的浅薄感受

    目前市面上 WPF的书籍 xff0c WPF揭秘 人民邮电出版社 深入解析 WPF编程 电子工业出版社 xff0c WPF程序设计指南 电子工业出版社 WPF高级编程 清华大学出版社 我购买了前面三本 xff0c 简单的对前面三本说一些浅薄
  • 麒麟操作系统配置web服务器,银河麒麟服务器设置

    银河麒麟服务器设置 内容精选 换一换 鲲鹏软件栈汇聚各种鲲鹏兼容软件 xff0c 帮助开发者了解如何将软件移植到鲲鹏上运行 xff0c 获取操作指导和工具 来自 xff1a 其他 对于业务量访问较大的业务 xff0c 可以通过ELB设置相应
  • 技术岗的职业规划_剪辑师该如何做好职业规划?

    各位点进来的小伙伴 xff0c 我猜你们在22 28岁之间吧 这是我们人生中最迷茫最不知所措的年龄段 刚大学毕业发现学的专业跟实际工作起来相差甚远 xff0c 茫然失措 工作几年后 xff0c 猛然发现每日的工作内容都差不多 xff0c 毫
  • debian11的PVE应用

    1 在debian11中安装pve7之后 xff0c 新建虚拟机安装openeuler 启动时报错 xff1a TASK ERROR start failed QEMU exited with code 1 可以把这一段 39 kvm ig
  • cvc 降噪_你买的“降噪”耳机真的是你想要的降噪吗?

    降噪 这一个高大上得词 xff0c 在你们眼中是不是非常的有效 xff0c 面对公共交通工具热播剧外放 xff0c 街道上车水马龙的轰鸣 xff0c 咖啡厅孩子们的喧嚣 xff0c 噪音其实一直都在我们的身边 xff0c 无处不在 xff0
  • ajax post请求怎么传参_高级前端:详解手写原生Ajax的实现

    点击上方 前端印象 xff0c 选择 设为星标 第一时间关注技术干货 xff01 对于Ajax xff0c 肯定很多小伙伴都听过甚至用过了 xff0c 那么没听过的也不用着急 xff0c 本文会对Ajax进行讲解 xff0c 其次 xff0
  • java版如何使区块常加载_Minecraft指令手册

    众所周知 xff0c 人是一种健忘的生物 所以作者忘记了Java版的常加载指令 幸亏一位书友留的言提醒了我 xff0c 不然Java版的各位就只能去网上查了 然后查到 xff0c 头上却起了大雾 滑稽 那么进入正题 xff1a Java版的
  • linux点歌机硬盘,自己动手给KTV点歌机换大硬盘

    某宝买的硬盘KTV点歌机 xff0c 当时买的是单主机没要触摸屏一体的 xff0c 所以硬盘容量最大只有1TB的 原来内置的歌曲 已经挺多的了 xff0c 剩余空间所剩无几 刚好有一块闲置的2TB硬盘就打算把它换上 可以看到剩余空间只有26
  • 云服务器 信息安全,云服务器的信息安全

    云服务器的信息安全 内容精选 换一换 北京时间1月3日 xff0c Intel处理器芯片被曝出存在严重的Meltdown和Spectre安全漏洞 xff0c 漏洞详情如下 xff1a 漏洞名称 xff1a Intel处理器存在严重芯片级漏洞
  • 千方百剂显示服务器错误,千方百剂远程服务器地址

    千方百剂远程服务器地址 内容精选 换一换 已成功登录Java性能分析 待安装Guardian的服务器已开启sshd 待安装Guardian的服务器已安装JRE xff0c JRE版本要求为Huawei JDK 8或者Open JDK 8 1
  • 天地伟业客户端服务器维护,天地伟业监控维保常见问题总结

    天地伟业监控维保常见问题总结 一 天地伟业监控维保监控报警种类不当 xff1a 天地伟业监控维保问题的描述 xff1a 智能监控技术有待发展 xff0c 一些警情尚难以有效研判准确报警 部分企业误导用户 xff0c 过度承诺 如 打架斗殴
  • mac时间机器文件服务器,Mac小技巧:时间机器的使用方法和细节

    时间机器是MacBook Pro上一个备份系统的内置软件 xff0c 这款软件对于大多数工作者来说绝对是一款神器 xff0c 能够让我们无限的找回到以前的Mac备份文件 xff0c 防止一不小心删除了重要文件等问题 xff0c 而且使用起来

随机推荐

  • 远程连接linux桌面之XDMCP配置

    使用xdmcp连接远程linux桌面 测试环境 xff1a Centos6 gnome桌面 kdm桌面涉及修改的文件不一样 xff09 确认以下组件被安装 xff1a yum gruopinstall 34 Desktop 34 34 De
  • snapper命令技巧

    在使用Btrfs时 xff0c 会用到snapper命令 xff0c 因为btrfs目前是最新的 xff0c 而且是稳定的文件系统 xff0c 说最新其实在2012年就已经有了 xff0c 但是真正作为默认文件系统来使用 xff0c 应该是
  • 邮件服务器配置+网页邮件收发

    在 之前 的 一 篇 的 博客 写 了 一 些 关 于 邮件 服务器 的 简单 的 配置 xff0c 这 篇 添加 了 在 网页 上 的 邮件 的 收发 和 用户 认证 等 相关 的 内容 好 了 xff0c 不 多 说 了 xff0c 开
  • winxp 连接linux ftp,Linux和XP之间使用FTP互传文件

    Linux和XP之间使用FTP互传文件 发布时间 2007 09 05 00 57 57来源 红联作者 rganizati 今天第一次付诸于行动 xff0c 发现其实很简单 xff0c 跟我们正常的两台Windows XP系统的机器之间使用
  • pandas所占内存释放

    df 61 pd read csv 39 39 要调用循环处理多个文件时 xff0c 内存占用情况严重 xff0c 如果互相之间不需要调用 xff0c 可以直接del df 释放内存
  • sxe客户端linux,Linux-kernel mailing list archive 2002-24,: [PATCH][swsusp] 2.4.19-pre10-ac2

    Florent Chabaud 8323584 1804289383 1024571187 61 19461 Content Type APPLICATION octet stream name 61 34 patch1 gz 34 Con
  • 打开Mac OSX原生的NTFS功能

    转载自 xff1a http www tianwaihome com 2014 07 mac osx ntfs html 打开Mac OSX原生的NTFS功能 很多同学都会为如何在Mac下写入NTFS格式的磁盘而感到困惑 xff0c 因为默
  • linux生成随机复杂密码,用Linux命令行生成随机密码的十种方法

    2011年的时候我写过一篇日志利用pwgen mkpasswd tr自动更改密码 xff0c 今天在51cto上翻译的与其相关的一篇国外文章 xff0c 名字就是本文的标题 当然方法上并不比我之前总结的高明 xff0c 这里也摘抄下具体实现
  • Linux的桌面环境gnome、kde、xfce、lxde 等等使用比较

    如果不是加入了图形界面 xff0c 微软的Windows系列操作系统不会成功地占领计算机桌面这块高地 这种人机交换的图形化界面 xff0c 使得界面更加直观 简易 而且更人性化 xff0c 同时也大大减少了使用者的认知负担 xff0c 普通
  • windows服务器不显示字体,Win10打开Word提示“Word无法显示所请求的字体”怎么办?...

    Win10打开Word提示 Word无法显示所请求的字体 怎么办 xff1f Word是我们最常使用的办公软件 xff0c 然而一位用户在Win10系统下打开Word时出错了 xff0c 系统提示 内存或磁盘空间不足 xff0c Word无
  • 在sublime text3中配置并使用LaTex

    准备工作 Sublime Text3 安装并配置好Package Control xff0c 若没有安装也没关系 xff0c 我已经把常用的插件都放到了我的GitHub xff0c 可以按照说明复制到指定路径即可 MiKTeX 下载并安装
  • Python爬取网站上面的数据很简单,但是如何爬取APP上面的数据呢

    前言 在我们在爬取手机APP上面的数据的时候 xff0c 都会借助Fidder来爬取 今天就教大家如何爬取手机APP上面的数据 环境配置 1 Fidder的安装和配置 下载Fidder软件地址 xff1a https www telerik
  • linux安装redis教程yum,linux下yum安装redis以及使用

    1 yum install redis 安装redis数据库 2 service redis start Redirecting to bin systemctl start redis service 开启redis服务 方式一 开启re
  • 存储过程:数据的插入和更新

    存储过程的功能非常强大 xff0c 在某种程度上甚至可以替代业务逻辑层 xff0c 接下来就一个小例子来说明 xff0c 用存储过程插入或更新语句 1 数据库表结构 所用数据库为Sql Server2008 2 创建存储过程 xff08 1
  • win10下VS2017配置GSL库

    GSL库 xff1a GNU Scientific Library 1 下载 xff1a 下载Complete package except sources和Sources两个exe文件 2 安装 xff1a 将两个exe安装 xff0c
  • 微信开放平台开发——网页微信扫码登录(OAuth2.0)

    1 OAuth2 0 OAuth xff08 开放授权 xff09 是一个开放标准 xff0c 允许用户让第三方应用访问该用户在某一网站上存储的私密的资源 xff08 如照片 xff0c 视频 xff0c 联系人列表 xff09 xff0c
  • 安全和取证Linux发行版Kali Linux 2018.4 发布

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 公告说 xff0c 欢迎来到2018年的第四个也是最后一个版本 xff0c Kali Linux 2018 4 xff0c 可以立即下载 这个版本将我们的内核升级到4 18
  • 使用Rust + Electron开发跨平台桌面应用 ( 二 )

    前言 在上一篇文章使用Rust 43 Electron开发跨平台桌面应用 一 中 xff0c 我们将Rust 43 Electron结合起来 xff0c 使用Rust编写核心业务逻辑 xff0c 并编译成node库提供给Electron的U
  • linux高级文件系统管理——btrfs

    前几天 xff0c 关于高级文件系统方面也给大家分享过RAID和LVM xff0c 今天给大家分享的这款文件系统可能比这两者更先进 xff0c 可以将其二者合二为一 第一 xff0c 它可以使用磁盘或者分区大小不一样的设备组建RAID xf
  • 字符串 - 字符串排序

    1 字符串排序 对于许多排序应用来说 xff0c 决定顺序的键都是字符串 给定一列字符串 xff0c 需要按一定顺序排列整齐方便后序处理 2 键索引计数法 这个方法名字有点拗口 xff0c 过程有点绕 xff0c 但是每一步其实很简单 举个