字符串排序:键索引计数法

2024-08-30 10:18

本文主要是介绍字符串排序:键索引计数法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

字符串排序:键索引计数法

  • 描述
  • 适用性
  • 步骤
    • 1、频率统计
    • 2、构建索引
    • 3、数据分类
    • 4、回写数组
  • 代码实现
  • 总结
  • 参考

描述

关于字符串的排序有很多种方式,像《算法》一书中列举的低位优先、高位优先等,其中最先提到的是键索引计数法,它也是其他排序方式的基础,我们先来了解下。

适用性

关于键索引计数法进行字符串排序,并不是全部都适用,因为它的排序算法核心就是通过统计元素出现频次、构建排序因子的索引边界来递进式完成所有元素排序,它主要适合于以下场景:

  • 用于小整数键的算法
    比如数组arr ={1,2,3,4,2,3,4,2,1,3,4,2,3,4},它里面重复的数字比较多,不重复的只有1,2,3,4,这时就可以用此方法。
  • 用于小整数键的分组排序
    还可以应用在基于小整数键的分组排序,比如有字母{a,b,c,d,e,f,g,h},各字母不重复、但是分组重复,其分组序号格式{字母,分组号}描述为{a,1}、{b,2}、{c,1}、{d,2}、{e,3}、{f,4}、{g,4}、{h,1},最终按照分组号进行排序实现的元素排列为a、c、h、b、d、e、f、g
    在这里插入图片描述
    综上,我们可以看到按照分组号可以将元素归纳如下:
分组号元素
1a、c、h
2b、d
3e
4f、g

步骤

1、频率统计

在这里插入图片描述
我们可以看到,每个分组出现频次如下:

分组号元素元素出现频次
1a、c、h3
2b、d2
3e1
4f、g2

统计频次的目的是为了给构建索引提供条件,我们知道所谓键索引计数就是通过索引 + 频次来完成的。索引可以理解为每个分组的排序边界,每个分组的起始索引即较小一侧边界,而每个分组的结束索引即较大一侧边界,如果索引边界为startIndexendIndex,分组内元素出现频次为t,那么每个分组中的索引边界和分组内元素出现频次的关系是endIndex = startIndex + t,每个分组都按照逻辑序号紧紧相邻,较大的分组起始索引与它相邻的第一个较小分组的结束索引一致。

如果将这个场景延展到一个直线上,也可以将索引边界理解为坐标点,将频次理解为步长,或者是坐标点之间的间距

2、构建索引

在这里插入图片描述
当已知了间距,下面根据间距从0开始计算和整理索引边界,可以参考上图,方法很简单,是从0开始递增每个分组的频次即可。

3、数据分类

在这里插入图片描述
当建立好索引后,下面开始进行数据分类,说白了这一步就是将元素排序填充的过程,因为已经知道了所有排序分组的起止边界了,也知道每个分组的容量了,接下来就是挨个映射填充就可以完成排序工作了。

分组元素填充后,起始索引递增
这里面的填充技巧的细节点在于,每填充一个分组内元素后,将对应的该分组的起始索引递增1,代表完成了一个分组内地排序,若后续还有同样分组内的元素填充则理所当然填充到该分组的下一个临近位即可。

4、回写数组

这一步是将已排序好的元素重新回写到原数组中即可。

代码实现

  • 纯小整数版
/*** @author: <a href=mailto:keycasiter@qq.com>guanjian</a>* @date: 2021/4/8 13:15* @description: */
public class IndexCountSortDemo {public static void main(String[] args) {int[] nums = {2, 3, 4, 1, 2, 4, 3, 1, 2, 2, 1};indexCountIndex(nums);//打印结果   1 1 1 2 2 2 2 3 3 4 4}public static void indexCountIndex(int[] nums) {int[] count = new int[6];//计算频率for (int i = 0; i < nums.length; i++) {count[nums[i] + 1]++;}//将频率转化为索引for (int i = 1; i < count.length; i++) {count[i] = count[i] + count[i - 1];}//数据分类int[] aux = new int[nums.length];for (int i = 0; i < nums.length; i++) {aux[count[nums[i]]++] = nums[i];//aux[count[nums[i]]] = nums[i];//count[nums[i]]++;}//回写数据(这里是打印)for (int i = 0; i < nums.length; i++) {System.out.print(aux[i] + " ");}}
}
  • 小整数分组排序元素
/*** @author: <a href=mailto:keycasiter@qq.com>guanjian</a>* @date: 2021/4/8 13:15* @description: */
public class IndexCountSortDemo {public static class Item<T> {private int group;private T data;public Item(int group, T data) {this.group = group;this.data = data;}public int getGroup() {return group;}public void setGroup(int group) {this.group = group;}public T getData() {return data;}public void setData(T data) {this.data = data;}}public static void main(String[] args) {Item<String>[] arr = new Item[]{new Item(1, "a"),new Item(2, "b"),new Item(1, "c"),new Item(2, "d"),new Item(3, "e"),new Item(4, "f"),new Item(4, "g"),new Item(1, "h")};indexCountIndexByItem(arr);//打印结果   a c h b d e f g}public static void indexCountIndexByItem(Item[] arr) {int[] count = new int[6];//计算频率for (int i = 0; i < arr.length; i++) {count[arr[i].group + 1]++;}//将频率转化为索引for (int i = 1; i < count.length; i++) {count[i] = count[i] + count[i - 1];}//数据分类Item[] aux = new Item[arr.length];for (int i = 0; i < arr.length; i++) {aux[count[arr[i].group]++] = arr[i];// aux[count[arr[i].group]] = arr[i];// count[arr[i].group]++;}//回写数据(这里是打印)for (int i = 0; i < arr.length; i++) {System.out.print(aux[i].data + " ");}}
}

总结

键索引计数法是一种对于小整数键排序非常有效却常常被忽略的排序方法。理解它的工作原理是理解字符串排序的第一步,它是一个线性时间级别的排序方法。

参考

字符串排序:键索引计数法
《算法》第4版

这篇关于字符串排序:键索引计数法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120534

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

Java实现Elasticsearch查询当前索引全部数据的完整代码

《Java实现Elasticsearch查询当前索引全部数据的完整代码》:本文主要介绍如何在Java中实现查询Elasticsearch索引中指定条件下的全部数据,通过设置滚动查询参数(scrol... 目录需求背景通常情况Java 实现查询 Elasticsearch 全部数据写在最后需求背景通常情况下

Pandas中多重索引技巧的实现

《Pandas中多重索引技巧的实现》Pandas中的多重索引功能强大,适用于处理多维数据,本文就来介绍一下多重索引技巧,具有一定的参考价值,感兴趣的可以了解一下... 目录1.多重索引概述2.多重索引的基本操作2.1 选择和切片多重索引2.2 交换层级与重设索引3.多重索引的高级操作3.1 多重索引的分组聚

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序