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开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...
随机推荐
- 自己修改select的样式(修改select右边的小三角)
CSS就可以解决,原理是将浏览器默认的下拉框样式清除,然后应用上自己的,再附一张向右对齐小箭头的图片即可. select { /*Chrome和Firefox里面的边框是不一样的,所以复写了一下*/ ...
- 字符串匹配之KMP算法
KMP算法使用前缀函数来模拟有限自动机的后缀函数,前缀函数通过计算模式与其自身的偏移匹配的信息,本身的证明很复杂,关键在于弄懂其核心思想,下面就不赘述了,仅仅贴出代码: #include <io ...
- SVN版本控制安装配置说明
版本控制好工具有SVN.CVS.VSS等多种,他们的优劣在此不说明,请网络参阅. SVN支持多种平台,此文仅描述Windows平台下使用说明. SVN客户包含客户端和服务端.Windows平台下客户端 ...
- 如何在Windows中打开多个Windows Media Player
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何在Windows中打开多个Windows Media Player.
- myeclipse中使用gradle开发项目
gradle可以直接使用maven的代码库,并且支持编程,可以说是maven的加强版.今天我们学习下,如何在MyEclipse下使用gradle开发项目.我们的开发环境:myeclipse 2015, ...
- SQL Server解决死锁问题
用以下语句查询所有死锁的进程号和表名: SELECT request_session_id spid, OBJECT_NAME( resource_associated_entity_id ...
- android109 结构体,联合体,枚举,自定义
#include <stdio.h> #include <stdlib.h> void study(){ printf("吃饭睡觉打李志\n"); } // ...
- Top 10 Questions about Java Exceptions--reference
reference from:http://www.programcreek.com/2013/10/top-10-questions-about-java-exceptions/ This arti ...
- the assignment of reading paper
在 IEEE 上找到Increasing Dependability of Component-based Software Systems by Online Failure Prediction, ...
- Java并发——同步容器与并发容器
同步容器类 早期版本的JDK提供的同步容器类为Vector和Hashtable,JDK1.2 提供了Collections.synchronizedXxx等工程方法,将普通的容器继续包装.对每个共有方 ...