数据结构与算法——基数排序简单Java实现
基数排序(radix sort)又称“桶子法”,在对多个正整数进行排序时可以使用。它的灵感来自于队列(Queue),它最独特的地方在于利用了数字的有穷性(阿拉伯数字只有0到9的10个)。
基数排序使用11个动态数组实现排序算法,一个主队列(下文都将使用的动态数组称为队列)存储未排序的数据(最后排序完成也仍然可以用它存储,或者如果希望保存原来的数据位置则可能需要增加一个队列);10个子队列用于排序过程中动态存放数值,在排序开始前和结束后可以清空。
我们使用LinkedList类来实现基数排序,其实整个类很简单,我先贴出全部代码然后再细细解释:
package ahe.sort; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList; /**
* 基数排序算法
*
* @author Johness
*
*/
public class RadixSort { /** 主队列 */
private LinkedList<Integer> mainQueue;
/** 子队列 */
private LinkedList<Integer>[] subQueues;
/** 子队列个数,作用不大 */
private final int SIZE = 10;
/** 当前容器(主队列)中存储数值的最大位数 */
private int maxDigits; /** 构造函数 */
public RadixSort() {
mainQueue = new LinkedList<Integer>();
subQueues = new LinkedList[SIZE];
for(int i = 0; i < SIZE; ++i)
subQueues[i] = new LinkedList<Integer>();
maxDigits = 0;
} /** 向容器中(主队列)添加一个数值 */
public void add(Integer num) {
int digits = String.valueOf(num).length();
if (digits > maxDigits)
maxDigits = digits;
mainQueue.add(num);
} /** 排序 */
public void sort() {
for (int i = 1; i <= maxDigits; ++i) {
while (mainQueue.size() > 0) {
Integer element = (Integer) mainQueue.pop();
String elementTmpStr = String.valueOf(element);
if (elementTmpStr.length() < i) {
subQueues[0].add(element);
continue;
}
int digit = elementTmpStr.charAt(elementTmpStr.length() - i) - '0';
subQueues[digit].add(element);
}
//listSubQueues();
for (int j = 0; j < SIZE; ++j) {
mainQueue.addAll(subQueues[j]);
subQueues[j].clear();
}
//listMainQueue();
}
} /*==============================================================================================*/
// 以下方法为测试方法(以下方法来自于Arizona State University学校课后作业,本人只做翻译,如该资源侵犯了您的权益,请及时联系我)
// 您可以访问
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/Assignment11.java
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/Sorting.java
// 查看本文参考内容
// 本文输入输出对照表可从该课后作业中获得
// 输入表
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/input1.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/input2.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/input3.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/input4.txt
// 输出表
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/output1.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/output2.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/output3.txt
// https://courses.eas.asu.edu/cse205/current/assignments/assignment11/output4.txt
/*==============================================================================================*/
/**
* 列举(输出)主队列数据
*/
public void listMainQueue() {
System.out.println("mainQueue = " + listQueue(mainQueue) + "\n");
} /**
* 列举(输出)子队列数据
*/
public void listSubQueues() {
String result = "";
for (int i = 0; i < SIZE; i++) {
result += "subQueue[" + i + "]:";
result += listQueue(subQueues[i]);
result += "\n";
}
System.out.println(result);
} /**
* 列举某队列中数据项
*
* 方法使用了一个临时队列来完成数据轮循
* 先从目标队列中逐个取出(采用取出并删除的方式)放入临时队列并做列举操作(连接到返回字符串)
* 待轮循完成后再将临时队列中的数据存入回目标队列
*
* @param queue 目标队列
* @return 包含目标队列中所有数据的字符串
*/
private String listQueue(LinkedList<Integer> queue) {
LinkedList<Integer> temp = new LinkedList<Integer>();
String result = "{ "; while (!queue.isEmpty()) {
Integer removed = queue.remove();
result += removed + " ";
temp.offer(removed);
}
result += "}\n"; while (!temp.isEmpty()) {
Integer removed2 = temp.remove();
queue.offer(removed2);
}
return result;
} public static void main(String[] args) {
char input1;
String inputInfo = new String();
String line = new String(); RadixSort sort1 = new RadixSort(); try {
// 打印菜单
printMenu(); // 创建流读取器读取用户输入
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(isr); do {
System.out.print("你想进行什么操作?\n");
line = stdin.readLine().trim(); // 读取一行
input1 = line.charAt(0);
input1 = Character.toUpperCase(input1); if (line.length() == 1) // 检查输入指令是否为单个
// 字符
{
switch (input1) {
case 'A': // 添加一个数值
System.out.print("请输入要添加的数值:\n");
inputInfo = stdin.readLine().trim();
int num = Integer.parseInt(inputInfo);
sort1.add(num);
System.out.print("数值添加成功\n");
break;
case 'L': // 列举数值
sort1.listMainQueue();
break;
case 'Q': // 退出
break;
case 'S': // 排序
sort1.sort();
System.out.print("排序完成\n");
break;
case '?': // 显示帮助
printMenu();
break;
default:
System.out.print("未知指令\n");
break;
}
} else {
System.out.print("未知指令\n");
}
} while (input1 != 'Q' || line.length() != 1);
} catch (IOException exception) {
System.out.print("IO Exception\n");
}
} /** 打印控制台界面(菜单) */
public static void printMenu() {
System.out.print("选项\t\t动作\n" + "------\t\t------\n"
+ "A\t\t添加一个数值\n" + "L\t\t列举队列\n"
+ "Q\t\t退出\n" + "S\t\t排序数据\n"
+ "?\t\t显示帮助\n\n");
}
}
我们直接看sort方法(行43至62),在略去了每次排序数据从子队列存回主队列的代码(行56至59)后我们的排序算法主要分为两层。
外层一共需要循环最大数值位数次,内层(每次)则是需要循环数值个数次。以{1,22,333,4444}为例,外层为4次循环(最大数4444为4位数),内层为4次循环(共有4个元素需要排序)。
我们把排序过程中列举队列的代码取消注释(行55和60),我们使用输入表1进行输入:
a
539
a
264
a
372
a
424
a
419
a
129
a
322
a
544
a
367
l
s
l
q
对应输出表则应该如下(部分空白我去除了):
选项 动作
------ ------
A 添加一个数值
L 列举队列
Q 退出
S 排序数据
? 显示帮助 你想进行什么操作?
a
请输入要添加的数值:
539
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
264
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
372
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
424
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
419
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
129
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
322
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
544
数值添加成功
你想进行什么操作?
a
请输入要添加的数值:
367
数值添加成功
你想进行什么操作?
l
mainQueue = { 539 264 372 424 419 129 322 544 367 }
你想进行什么操作?
s
subQueue[0]:{ }
subQueue[1]:{ }
subQueue[2]:{ 372 322 }
subQueue[3]:{ }
subQueue[4]:{ 264 424 544 }
subQueue[5]:{ }
subQueue[6]:{ }
subQueue[7]:{ 367 }
subQueue[8]:{ }
subQueue[9]:{ 539 419 129 }
mainQueue = { 372 322 264 424 544 367 539 419 129 }
subQueue[0]:{ }
subQueue[1]:{ 419 }
subQueue[2]:{ 322 424 129 }
subQueue[3]:{ 539 }
subQueue[4]:{ 544 }
subQueue[5]:{ }
subQueue[6]:{ 264 367 }
subQueue[7]:{ 372 }
subQueue[8]:{ }
subQueue[9]:{ }
mainQueue = { 419 322 424 129 539 544 264 367 372 }
subQueue[0]:{ }
subQueue[1]:{ 129 }
subQueue[2]:{ 264 }
subQueue[3]:{ 322 367 372 }
subQueue[4]:{ 419 424 }
subQueue[5]:{ 539 544 }
subQueue[6]:{ }
subQueue[7]:{ }
subQueue[8]:{ }
subQueue[9]:{ }
mainQueue = { 129 264 322 367 372 419 424 539 544 }
排序完成
你想进行什么操作?
l
mainQueue = { 129 264 322 367 372 419 424 539 544 }
你想进行什么操作?
q
(你可以将列举子队列的语句行55放入输出更频繁的地方如原行49后和52后,这样更加能直观地看到效果)
从上面的输出表可以看出,排序轮循一共进行了3次(外层,因为数值最大位数为3)。
好,不多说了,大家领会精神。
欢迎您移步我们的交流群,无聊的时候大家一起打发时间:
或者通过QQ与我联系:
(最后编辑时间2013-11-22 22:38:04)
数据结构与算法——基数排序简单Java实现的更多相关文章
- 大公司面试经典数据结构与算法题C#/Java解答
几个大公司(IBM.MicroSoft and so on)面试经典数据结构与算法题C#解答 1.链表反转 我想到了两种比较简单的方法 第一种是需要开一个新的链表,将原链表的元素从后到前的插入到新链表 ...
- 【Java数据结构与算法】简单排序、二分查找和异或运算
简单排序 选择排序 概念 首先,找到数组中最小的那个元素,其次,把它和数组的第一个元素交换位置(如果第一个元素就是最小的元素那么它就和自己交换).再次,在剩下的元素中找到最小的元素,将它与数组的第二个 ...
- 基数排序简单Java实现
基数排序(radix sort)又称“桶子法”,在对多个正整数进行排序时可以使用.它的灵感来自于队列(Queue),它最独特的地方在于利用了数字的有穷性(阿拉伯数字只有0到9的10个). 基数排序使用 ...
- 排序算法-基数排序(Java)
package com.rao.sort; import java.util.*; /** * @author Srao * @className RadioSort * @date 2019/12/ ...
- 数据结构与算法笔记(java)目录
数据结构: 一个动态可视化数据结构的网站 线性结构 数组 动态数组 链表 单向链表 双向链表 单向循环链表 双向循环链表 栈 栈 队列 队列 双端队列 哈希表 树形结构 二叉树 二叉树 二叉搜索树 A ...
- Java数据结构和算法(六)--二叉树
什么是树? 上面图例就是一个树,用圆代表节点,连接圆的直线代表边.树的顶端总有一个节点,通过它连接第二层的节点,然后第二层连向更下一层的节点,以此递推 ,所以树的顶端小,底部大.和现实中的树是相反的, ...
- java数据结构和算法01(数组的简单使用)
一直都对这一块没有什么想法,加上不怎么理解,只是懂个大概:最近突然感觉对数据结构和算法这块有点儿兴趣,决定还是尽量详细的看看这些结构和算法: 话说什么事数据结构和算法呢?现在我也说不上来,等我学的差不 ...
- Java数据结构和算法 - 简单排序
Q: 冒泡排序? A: 1) 比较相邻的元素.如果第一个比第二个大,就交换它们两个; 2) 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数; 3) 针 ...
- Java数据结构和算法 - 高级排序
希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...
随机推荐
- iOS:百度长语音识别具体的封装:识别、播放、进度刷新
一.介绍 以前做过讯飞语音识别,比较简单,识别率很不错,但是它的识别时间是有限制的,最多60秒.可是有的时候我们需要更长的识别时间,例如朗诵古诗等功能.当然讯飞语音也是可以通过曲线救国来实现,就是每达 ...
- iOS开发-观察者模式
观察者模式也被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己.观察者模式中 ...
- 关于unity3dGUI(uGUI)的一些自适应的收获,在这里跟大家分享一下
假设大家要转载这篇文章,请注明出处.本人名字叫赖张殷,博客地址为http://my.csdn.net/?c=674f97f953e5dbfdba9fefaa3d1fcbe1 //2017年5月12日改 ...
- SoapUI Pro Project Solution Collection –Easy develop Groovy Script to improve SoapUI ability
As you know the groovy script and java script language is the soapui supported .but unfortunately So ...
- SCWS 中文分词_测试成功
地址: http://www.xunsearch.com/scws/index.php
- Apache学习---多进程处理模块(MPM)原理详解
查看Apache的模式,可以使用httpd -V命令来查看: 1. prefork MPM prefork模式可以算是很古老但是非常稳定的Apache模式.Apache在启动之初,就预先fork一些子 ...
- MySQL 数据的 截取,数据清洗
Mysql字符串截取函数SUBSTRING的用法说明 函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(conte ...
- [CTCI] 最小调整有序
最小调整有序 题目描述 有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的.注意:n-m应该越小越好,也就是说,找出符合条件的最短序列. 给定一个int数 ...
- Mac下软件包管理器-homebrew
类似于redhat系统的yum,ubuntu的apt-get,mac系统下也有相应的包管理容器:homebrew.用法与apt-get.yum大同小异,都是对安装软件做一些安装删除类的命令行操作,以下 ...
- Asp.Net T4模板生成三层架构
1.T4 Editor安装 T4:根据模板生成文件,例如model等 vs中默认t4模板编码是没有提示和高亮的,需使用以下插件,免费的 https://t4-editor.tangible-engin ...