7种基本排序算法的Java实现
7种基本排序算法的Java实现
以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息。
以下为代码片段,完整的代码见Sort.java
- 插入排序
/**
* 直接插入排序
* 不稳定
* 时间复杂度:O(n^2)
* 最差时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 使用场景:大部分元素有序
* @param elements
* @param comparator
* @param <T>
*/
public <T> void insertSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
} int length = elements.length;
for (int i = 1; i < length; i++) {
T current = elements[i];
int j;
for (j = i; j > 0; j--) {
if (comparator.compare(elements[j - 1], current) > 0) {
elements[j] = elements[j - 1];
} else {
break;
}
}
elements[j] = current;
}
}
- Shell排序
/**
* 希尔排序
* 不稳定
* 时间复杂度:O(nlogn)
* 最差时间复杂度:O(n^s) 1<s<2
* 空间复杂度:O(1)
* 使用场景:元素小于5000
* @param elements
* @param comparator
* @param <T>
*/
public <T> void shellSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
}
int length = elements.length;
for (int gap = length/2; gap >= 1; gap /= 2) {
for (int i = gap; i < length; i++) {
T current = elements[i];
int j;
for (j = i; j >= gap; j = j - gap) {
if (comparator.compare(elements[j - gap], current) > 0) {
elements[j] = elements[j - gap];
} else {
break;
}
}
elements[j] = current;
}
// printArray(elements, "gap:" + gap);
}
}
- 选择排序
/**
* 选择排序
* 稳定
* 时间复杂度:O(n^2)
* 最差时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 使用场景:n较少时
* @param elements
* @param comparator
* @param <T>
*/
public <T> void selectSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
} int length = elements.length;
for (int i = 0; i < length - 1; i++) {
int min = i;
for (int j = i + 1; j < length; j++) {
if (comparator.compare(elements[min], elements[j]) > 0) {
min = j;
}
}
if (min != i) {
swap(elements, min, i);
}
}
}
- 堆排序
优先级队列内部实现就是一个最小堆,这里就不自己实现heap了
/**
* 堆排序
* 时间复杂度:O(nlogn)
* 最差时间复杂度:O(nlogn)
* 空间复杂度:O(n)
* 使用场景:n较大时
* @param elements
* @param comparator
* @param <T>
*/
public <T> void heapSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
} PriorityQueue<T> heap = new PriorityQueue(elements.length, comparator);
for (T element : elements) {
heap.add(element);
}
for (int i = 0; i < elements.length; i++) {
elements[i] = heap.poll();
}
}
- 冒泡排序
/**
* 冒泡排序
* 稳定
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* 使用场景:n较小时
* @param elements
* @param comparator
* @param <T>
*/
public <T> void bubbleSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
} int length = elements.length;
for (int i = 1; i < length; i++) {
for (int j = length - 1; j >= i; j--) {
if (comparator.compare(elements[j - 1], elements[j]) > 0) {
swap(elements, j - 1, j);
}
}
}
}
- 快排
/**
* 快速排序
* 不稳定
* 时间复杂度:O(nlogn)
* 最差时间复杂度:O(n^2)
* 空间复杂度:O(logn)
* 使用场景:由于是递归,不适合内存有限制的情况, n较大时
* @param elements
* @param comparator
* @param <T>
*/
public <T> void quickSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
}
doQuickSort(elements, 0, elements.length - 1, comparator);
} private <T> void doQuickSort(T[] elements, int start, int end, Comparator<T> comparator) {
if (start >= end) {
return;
}
int pivot = partition(elements, start, end, comparator);
doQuickSort(elements, start, pivot - 1, comparator);
doQuickSort(elements, pivot + 1, end, comparator);
} private <T> int partition(T[] elements, int start, int end, Comparator<T> comparator) {
T pivot = elements[start];
int pivotIndex = start, forward = start, back = end;
while (forward < back) {
for (; comparator.compare(pivot, elements[forward]) >= 0 && forward < end; forward++) {}
for (; comparator.compare(pivot, elements[back]) <= 0 && back > start; back--) {}
if (forward < back) {
swap(elements, forward++, back--);
}
}
swap(elements, back, pivotIndex);
return back;
}
- 归并排序
/**
* 归并排序
* 不稳定
* 时间复杂度:O(nlogn)
* 最差时间复杂度:O(nlogn)
* 空间复杂度:O(n)
* 使用场景:n较大时
* @param elements
* @param comparator
* @param <T>
*/
public <T> void mergeSort(T[] elements, Comparator<T> comparator) {
if (isInputInvalid(elements, comparator)) {
return;
} Object[] aux = new Object[elements.length];
int start = 0, end = elements.length - 1;
doMergeSort(elements, start, end, comparator, aux);
} private <T> void doMergeSort(T[] elements, int start, int end, Comparator<T> comparator, Object[] aux) {
if (start >= end) {
return;
}
int mid = (start + end) / 2;
doMergeSort(elements, start, mid, comparator, aux);
doMergeSort(elements, mid + 1, end, comparator, aux);
merge(elements, start, mid, end, comparator, aux);
} private <T> void merge(T[] elements, int start, int mid, int end, Comparator<T> comparator, Object[] aux) {
int lb = start, rb = mid + 1, auxIndex = start;
while (lb <= mid && rb <= end) {
if (comparator.compare(elements[lb], elements[rb]) <= 0) {
aux[auxIndex++] = elements[lb++];
} else {
aux[auxIndex++] = elements[rb++];
}
} if (lb < mid + 1) {
while(lb <= mid) {
aux[auxIndex++] = elements[lb++];
}
} else {
while(rb <= end) {
aux[auxIndex++] = elements[rb++];
}
} for(int i = start; i <= end; i++) {
elements[i] = (T) aux[i];
}
}
- 测试用方法
public static void main(String[] args) {
Integer[] elements = {3, 543, 54, 5, 6, 2, 67, 3, 65, 4};
// Integer[] elements = {0,0,0,0,0,0,0,0,0,0,0};
printArray(elements, "OriginalArray");
Sort sort = new Sort();
Integer[] dupArray = dupArray(elements);
sort.bubbleSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "BubbleSort");
dupArray = dupArray(elements);
sort.insertSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "InsertSort");
dupArray = dupArray(elements);
sort.selectSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "SelectSort");
dupArray = dupArray(elements);
sort.heapSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "HeapSort");
dupArray = dupArray(elements);
sort.quickSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "QuickSort");
dupArray = dupArray(elements);
sort.shellSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "ShellSort");
dupArray = dupArray(elements);
sort.mergeSort(dupArray, (o1, o2) -> o1 - o2);
printArray(dupArray, "MergeSort");
}
private static <T> T[] dupArray(T[] array) {
return Arrays.copyOf(array, array.length);
}
private static <T> void printArray(T[] array, String des) {
System.out.println(arrayToString(array) + " :" + des);
}
public static <T> String arrayToString(T[] array) {
StringBuilder resultBuilder = new StringBuilder();
resultBuilder.append("{");
for (T item : array) {
resultBuilder.append(item).append(",");
}
resultBuilder.deleteCharAt(resultBuilder.length() - 1);
resultBuilder.append("}");
return resultBuilder.toString();
}
当然每种算法根据自身的缺陷都有可以改进的地方,可以结合不同的情况使用不同的排序算法,比如快排中使用三者取中的pivot选取方法,或者在快排在递归到比较小的元素划分的时候使用插入排序等等。
文中有不足之处还请大家批评指正。
7种基本排序算法的Java实现的更多相关文章
- 七种经典排序算法及Java实现
排序算法稳定性表示两个值相同的元素在排序前后是否有位置变化.如果前后位置变化,则排序算法是不稳定的,否则是稳定的.稳定性的定义符合常理,两个值相同的元素无需再次交换位置,交换位置是做了一次无用功. 下 ...
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...
- 几种常见排序算法的java实现
一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...
- 三种简单排序算法(java实现)
一.冒泡排序 算法思想:遍历待排序的数组,每次遍历比较相邻的两个元素,如果他们的排列顺序错误就交换他们的位置,经过一趟排序后,最大的元素会浮置数组的末端.重复操 作 ...
- 几大排序算法的Java实现
很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...
- 6种基础排序算法java源码+图文解析[面试宝典]
一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...
- 几种简单的排序算法(JAVA)
几种排序算法(JAVA) 一.代码 package com.hdwang; import java.util.Arrays; /** * Created by admin on 2017/1/20. ...
- 常见排序算法总结 -- java实现
常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...
- 十大经典排序算法(java实现、配图解,附源码)
前言: 本文章主要是讲解我个人在学习Java开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...
随机推荐
- javascript 如何判断一个对象的类型
<!DOCTYPE html> <html> <head> </head> <body> <script type="tex ...
- JBOSS实现RMI时注意的问题
使用JBOSS部署EJB服务后通过RMI访问报错: javax.naming.CommunicationException: Could not obtain connection to any of ...
- Git简介:
Git中文文档 1.详解在Visual Studio中使用git版本系统(图文) 2.GitExtensions下载地址:http://gitextensions.codeplex.com/ 3.Gi ...
- java中服务器启动时,执行定时任务
package com.ripsoft.util; import java.util.Calendar; import java.util.Timer; import javax.servlet.Se ...
- Symfony VarDumper Component
Symfony VarDumper 类似 php var_dump() 官方文档写的安装方法 : 按照步骤 就可以在 running any PHP code 时候使用了 In order to h ...
- [置顶] 项目进阶 之 持续构建环境搭建(二)Nexus私服器
上一篇博文项目进阶 之 持续构建环境搭建(一)架构中,我们大致讲解了一下本系列所搭建环境的基本框架,这次开始我们进入真正的环境搭建实战.重点不在于搭建的环境是否成功和完善,而是在搭建过程中充分认识到每 ...
- 用普通PC主板的蜂鸣器给树莓派(RPI)加个报警器
这两天有点时间,捣鼓了下那闲置好久的树莓派,把普通PC主板的蜂鸣器作为树莓派的报警器用. Raspberry Pi有许多的GPIO(General Purpose Input Output:通用输入/ ...
- Python实现二叉树的前序遍历、中序遍历
计算根节点到叶子节点的所组成的数字(1247, 125, 1367)以及叶子节点到根节点组成的数字(7421, 521, 8631),其二叉树树型结构如下 计算从根节点到叶子节点组成的数字,本质上来说 ...
- 准备开一个地图SDK的开源项目
最近有点空闲时间了, 准备开一个地图SDK的开源项目, 现在的地图SDK已经有很多了, 再做一个跟重新发明个轮子差不多, 但还想做的原因是想在别的轮子的基础上造个轮子... 初步设想是基于开源的地图渲 ...
- 使用new分配内存的类需要自己定义拷贝构造函数
13.22 假定我们希望HasPtr的行为像一个值.即,对于对象所指向的string成员,每个对象都有一份自己的拷贝. #include<iostream> #include<str ...