数据结构与算法之非比较排序【Java】
比较排序与非比较排序的对比
常见的快速排序、归并排序、堆排序、冒泡排序等属于比较排序。在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置。在冒泡排序之类的排序中,问题规模为n,又因为需要比较n次,所以平均时间复杂度为O(n²)。在归并排序、快速排序之类的排序中,问题规模通过分治法消减为logN次,所以时间复杂度平均O(nlogn)。比较排序的优势是,适用于各种规模的数据,也不在乎数据的分布,都能进行排序。可以说,比较排序适用于一切需要排序的情况。
计数排序、基数排序、桶排序则属于非比较排序。非比较排序是通过确定每个元素之前,应该有多少个元素来排序。针对数组arr,计算arr[i]之前有多少个元素,则唯一确定了arr[i]在排序后数组中的位置。
非比较排序只要确定每个元素之前的已有的元素个数即可,所有一次遍历即可解决。算法时间复杂度O(n)。非比较排序时间复杂度底,但由于非比较排序需要占用空间来确定唯一位置。所以对数据规模和数据分布有一定的要求。
非比较排序
常见的比较排序主要有以下几种:基数排序、计数排序、桶排序。
基数排序
1、基本思想:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
2、算法实现
package com.allSorts; import java.util.ArrayList;
import java.util.List; /**
* Created by Demrystv.
*/
public class Ji1Shu {
public static void main(String[] args) {
int[] a = {23,45,67,88,90,21,42,52,73,61};
System.out.println("排序前:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
} //基数排序
sort(a); System.out.println("");
System.out.println("排序后:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
} private static void sort(int[] a){ //找到最大值,看最大值有几位,从而确定要比较几次,个十百千万。。。
int max = 0;
for(int i=0;i<a.length;i++){
if(max<a[i]){
max = a[i];
}
} //找到最大值后,确定要比较几次
int times = 0;
while (max>0){
max = max/10;
times++;
} //建立从0到9十个队列
List<ArrayList> list1 = new ArrayList<>();
for(int i=0;i<10;i++){
ArrayList list2 = new ArrayList();
list1.add(list2);
} //进行times次分配和收集,不断的重复即可。
for(int i=0;i<times;i++){ //分配,按照比较的所在的位的大小将其放入list1 中,类似于数组链表中的链表
for(int j=0;j<a.length;j++){
int x = a[j] % (int)Math.pow(10,i+1) / (int)Math.pow(10,i);
ArrayList list3 = list1.get(x);
list3.add(a[j]);
list1.set(x,list3);
} //收集,然后以此从数组的从左到右,链表的从上到下进行收集,将其重新放进一个新的数组中
int count = 0 ;
for(int j=0;j<10;j++){
while (list1.get(j).size()>0){
ArrayList<Integer> list4 = list1.get(j);
a[count] = list4.get(0);
list4.remove(0);
count++;
}
}
} }
}
3、分析
基数排序是稳定的排序算法。
基数排序的时间复杂度为O(k*n),空间复杂度为O(m),k为数组中数值的最大位数,m为桶的的个数。
计数排序
package com.allSorts; /**
* Created by Demrystv.
*/
public class Ji4Shu {
public static void main(String[] args) {
int[] a = {23,42,53,64,63,32,13,52,97,94,26};
System.out.println("排序前:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
} //计数排序
sort(a); System.out.println("");
System.out.println("排序后:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
} private static void sort(int[] a){ if(a==null || a.length==0){
return;
} int max=0,min=0;
for(int i=0;i<a.length;i++){
max = Math.max(max,a[i]);
min = Math.min(min,a[i]);
} int[] help = new int[max-min+1];
int pos; for(int i=0;i<a.length;i++){
pos = a[i]-min;
help[pos]++;
} int index=0;
for(int i=0;i<help.length;i++){
while (help[i]>0){
a[index] = i + min;
index++;
help[i]--;
}
}
}
}
3、分析
计数排序是稳定的排序算法。
计数排序的时间复杂度为O(k+n),空间复杂度为O(m),k为数组中最大数与最小数差值,m为桶的的个数。
桶排序
package com.allSorts; import java.util.ArrayList;
import java.util.Collections; /**
* Created by Demrystv.
*/
public class Tong {
public static void main(String[] args) {
int[] a = {32,45,42,51,53,86,95,53,93,55,59};
System.out.println("排序前:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
} //桶排序
sort(a); System.out.println("");
System.out.println("排序后:");
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
} private static void sort(int[] a){ if(a==null || a.length==0){
return;
} int max=0,min=0;
for(int i=0;i<a.length;i++){
max = Math.max(max,a[i]);
min = Math.min(min,a[i]);
} //确定桶数,并且建立一系列的桶
int bucketNum = (max-min)/a.length+1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for (int i=0;i<bucketNum;i++){
bucketArr.add(new ArrayList<Integer>());
} //将每个元素放入桶
for(int i=0;i<a.length;i++){
int num = (a[i]-min)/a.length;
bucketArr.get(num).add(a[i]);
} //对每个桶进行排序
for(int i=0;i<bucketArr.size();i++){
Collections.sort(bucketArr.get(i));
} int index = 0;
for(int i=0;i<bucketArr.size();i++){
while (bucketArr.get(i).size()>0){
a[index++] = bucketArr.get(i).get(0);
bucketArr.get(i).remove(0);
}
}
}
}
3、分析
数据结构与算法之非比较排序【Java】的更多相关文章
- 数据结构和算法(Golang实现)(25)排序算法-快速排序
快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...
- 数据结构和算法(Golang实现)(23)排序算法-归并排序
归并排序 归并排序是一种分治策略的排序算法.它是一种比较特殊的排序算法,通过递归地先使每个子序列有序,再将两个有序的序列进行合并成一个有序的序列. 归并排序首先由著名的现代计算机之父John_von_ ...
- 数据结构和算法(Golang实现)(24)排序算法-优先队列及堆排序
优先队列及堆排序 堆排序(Heap Sort)由威尔士-加拿大计算机科学家J. W. J. Williams在1964年发明,它利用了二叉堆(A binary heap)的性质实现了排序,并证明了二叉 ...
- 数据结构和算法(Golang实现)(18)排序算法-前言
排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...
- 数据结构和算法(Golang实现)(19)排序算法-冒泡排序
冒泡排序 冒泡排序是大多数人学的第一种排序算法,在面试中,也是问的最多的一种,有时候还要求手写排序代码,因为比较简单. 冒泡排序属于交换类的排序算法. 一.算法介绍 现在有一堆乱序的数,比如:5 9 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- 数据结构和算法(Golang实现)(21)排序算法-插入排序
插入排序 插入排序,一般我们指的是简单插入排序,也可以叫直接插入排序.就是说,每次把一个数插到已经排好序的数列里面形成新的排好序的数列,以此反复. 插入排序属于插入类排序算法. 除了我以外,有些人打扑 ...
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...
- Python数据结构与算法(几种排序)
数据结构与算法(Python) 冒泡排序 冒泡排序(英语:Bubble Sort)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是 ...
随机推荐
- oracle怎么建立本地连接
sqlplus连接oracle数据库(连接本地oracle数据库和连接远程的oracle数据库) 虽然我们现在平时都是使用PLSQL Developer这个软件工具了,但是我们还是要了解sqlplus ...
- asp.net MVC项目开发之统计图echarts后台数据的处理(三)
前台显示的东西,有相应的文档很容易修改,后台传递数据方式才是我们最关心的 首先要记住,我们一步数据使用的是post,那么后台代码我们要给方法加上 [HttpPost]注解 不然异步没有效果 下面上代码 ...
- C语言三(2)
多重 if...else....else 结构 语法: if(条件1) { 语句1; } else if(条件2) { 语句2; } else if(条件3) { 语句3; } else { 语句N; ...
- Go1.14发布了,快来围观新的特性啦
如期而至,Go1.14发布了,和往常一样,该版本保留了Go 1兼容性的承若,这个版本的大部分更新在工具链 .运行时库的性能提升方面,总的来说,还是在已有的基础上不断优化提成,大家期待的泛型还没有到来, ...
- C#设计模式学习笔记:(16)观察者模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7928521.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第四个模式--观 ...
- Android中DatePicker日期选择器的使用和获取选择的年月日
场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改 ...
- Maven 阿里云仓库地址
https://maven.aliyun.com/mvn/view 一般使用聚合仓库(group),path是仓库地址.可点击右上角“使用指南”: 附 目前阿里云仓库的地址 https://mav ...
- MySQL必知必会--汇 总 数 据
聚集函数 我们经常需要汇总数据而不用把它们实际检索出来,为此MySQL提 供了专门的函数.使用这些函数,MySQL查询可用于检索数据,以便分 析和报表生成.这种类型的检索例子有以下几种. 确定表中行数 ...
- Linux 文件、目录操作
Linux中的路径只能使用/,不能使用\ 或\\. cd 切换目录 cd / 切换到系统根目录,cd即change dir cd /bin 切换到根目录下的bin目录 cd .. ...
- 软件测试常见术语(英->汉)收藏好随时备用!
Defect 缺陷Defect Rate 缺陷率Verification & Validation 验证和确认Failure 故障White-box Testing 白盒测试Black-box ...