7种基本排序算法的Java实现

转自我的Github

以下为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实现的更多相关文章

  1. 七种经典排序算法及Java实现

    排序算法稳定性表示两个值相同的元素在排序前后是否有位置变化.如果前后位置变化,则排序算法是不稳定的,否则是稳定的.稳定性的定义符合常理,两个值相同的元素无需再次交换位置,交换位置是做了一次无用功. 下 ...

  2. 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)

    排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...

  3. 几种常见排序算法的java实现

    一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...

  4. 三种简单排序算法(java实现)

    一.冒泡排序 算法思想:遍历待排序的数组,每次遍历比较相邻的两个元素,如果他们的排列顺序错误就交换他们的位置,经过一趟排序后,最大的元素会浮置数组的末端.重复操                   作 ...

  5. 几大排序算法的Java实现

    很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...

  6. 6种基础排序算法java源码+图文解析[面试宝典]

    一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...

  7. 几种简单的排序算法(JAVA)

    几种排序算法(JAVA) 一.代码 package com.hdwang; import java.util.Arrays; /** * Created by admin on 2017/1/20. ...

  8. 常见排序算法总结 -- java实现

    常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...

  9. 十大经典排序算法(java实现、配图解,附源码)

    前言: 本文章主要是讲解我个人在学习Java开发环境的排序算法时做的一些准备,以及个人的心得体会,汇集成本篇文章,作为自己对排序算法理解的总结与笔记. 内容主要是关于十大经典排序算法的简介.原理.动静 ...

随机推荐

  1. 安装、配置JDK的步骤

    1.配置环境变量,打开我的电脑--属性--高级--环境变量,新建系统变量JAVA_HOME .变量值:jdk的目录,比如d:/java.选择“系统变量”中变量名为“Path”的环境变量双击该变量,把J ...

  2. careercup-递归和动态规划 9.2

    9.2 设想有个机器人坐在X*Y网格的左上角,只能向右.向下移动.机器人从(0,0)到(X,Y)有多少种走法? 进阶: 假设有些点为“禁区”,机器人不能踏足.设计一种算法,找到一条路径,让机器人从左上 ...

  3. spinner中的onNothingSelected方法到底什么时候调用?

    这个东东大家在开发中可能不太能用到,所以总是容易被忽略,由于工作原因,我最近琢磨了一下onNothingSelected方法的调用时机问题,其实很简单,只要我们稍微看一下源码就明白了: /** * C ...

  4. Android(java)学习笔记143:android提供打开各种文件的API接口:setDataAndType

    android 打开各种文件(setDataAndType) private void openFile(File file){ Intent intent = new Intent(); inten ...

  5. 使用CocoaPods遇到的几个坑,记录一下

    最近使用pod的时候升级到1.0.0版本后遇到一些坑,整理一下 首先是CocoaPods报错:The dependency `` is not used in any concrete target ...

  6. 解决在mybatis中使用CTE进行oracle查询数据类型为long的字段出现流关闭问题

    今天把notice表中的content字段改为long字段后,含有该字段的使用CTE的查询语句报错了.提示一下错误 ### Cause: java.sql.SQLException: 流已被关闭 ; ...

  7. JS设置打印页面并调用本地打印机打印页面

    <script type="text/javascript"> var hkey_key; var hkey_root = "HKEY_CURRENT_USE ...

  8. java strtus2 注解配置入门(一)

    因为工作的原因,所以接触到一些项目,有的项目虽然看着能有跟着做,可是具体里面的框架是别人配置的,具体框架还是不是非常的了解,所以这里在看一下我学到的 一点关于struts2中注解开发的一点点. 直接代 ...

  9. Redis 集群常见问题

    Redis集群相关问题 1:远程连接问题 远程连接保护模式下,需要做一些配置.

  10. python中关于正则表达式二

    2.2 反向引用 \1, \2... 表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来.在获取匹配结果的时候,小括号包含的表达式所匹配到的字符 ...