数据结构与算法之非比较排序【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)是一种简单的排序算法.它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.遍历数列的工作是 ...
随机推荐
- 深入了解MySQL,一篇简短的总结
MySQL的基本语法 这里作为MySQL部分模块的深入了解,大部分都是理论方面的笔记,不会写具体用法. 具体用法会记录在下面这个随笔分类下,不过暂时还没更新完,等过段时间会更新下事务.存储过程.索引等 ...
- c++头文件包含 #ifndef ##pragma once
2013-04-14 17:03 (分类:计算机程序) 烦死了,这种垃圾小问题很多,你又必须要知道.......在编写c++程序时,会编写多个类或者多个cpp文件,免不了要多次使用include包含头 ...
- [Redis-CentOS7]Redis数据持久化(八)
配置文件位置 /ect/redis.conf RDB存储配置 save 900 1 # 900秒之内发生一次写操作保存 save 300 10 # 300秒内写10次保存 save 60 10000 ...
- [Redis-CentOS7]Redis列表操作(三)
LPUSH添加列表 127.0.0.1:6379> LPUSH websites www.baidu.com (integer) 1 LRANGE 获取全部值 127.0.0.1:6379> ...
- Day17-18前端学习之路——Javascript事件
用户在某个元素上点击鼠标或悬停光标. 用户在键盘中按下某个按键. 用户调整浏览器的大小或者关闭浏览器窗口. 一个网页停止加载. 提交表单. 播放.暂停.关闭视频. 发生错误. 更多事件:https:/ ...
- Day3前端学习之路——CSS基本知识
课程目标 初步了解什么是CSS,掌握基本的CSS概念,语法,针对选择器特殊性的计算处理,以及学习如何设置一些简单的样式 任务一:回答问题 1.什么是CSS,CSS是如何工作的? CSS 指层叠样式表 ...
- es5实现一个class
es5实现一个class https://juejin.im/post/5ac1c5bf518825558949f898#heading-9
- np.vstack与np.hstack
转自:https://zhuanlan.zhihu.com/p/82996332 留作备忘
- 零基础Python应该怎样学习呢?(附视频教程)
Python应该怎样学习呢? 阶段一:适合自己的学习方式 对于零基础的初学者来说,最迷茫的是不知道怎样开始学习?那这里小编建议可以采用视频+书籍的方式进行学习.看视频学习可以让你迅速掌握编程的基础语法 ...
- Python3标准库:weakref对象的非永久引用
1. weakref对象的非永久引用 weakref模块支持对象的弱引用.正常的引用会增加对象的引用数,并避免它被垃圾回收.但结果并不总是如期望中的那样,比如有时可能会出现一个循环引用,或者有时需要内 ...