经典的排序算法总结

冒泡排序算法

算法描述:

  1. 比较相邻的元素:如果第一个比第二个大,就交换它们两个;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;

    重复步骤1~3,直到排序完成。

排序方式:in-place

时间复杂度:

  • 最佳情况:T(n) = O(n)
  • 最差情况:T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

    空间复杂度:O(1)

代码实现:

/*******bubble Sort algorithm **************/
public void bubble(int[] arr){//冒泡排序
for(int i = 0;i<arr.length;i++){
for(int j = 0;j<arr.length-1-i;j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}

选择排序算法:

算法描述:

n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。

初始状态:无序区为R[1…n],有序区为空;

第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1…i-1]和R(i…n)。该趟排序从当前无序区中-选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1…i]和R[i+1…n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;

n-1趟结束,数组有序化了。

排序方式:in-place

时间复杂度:

  • 最佳情况:T(n) = O(n2)
  • 最差情况:T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

    空间复杂度:O(1)

代码描述:

/*******Select Sort algorithm **************/
public void select(int[] arr){//选择排序
for(int i=0;i<arr.length;i++){
int min = arr[i];
int pos = -1;
boolean exc = false;//用来记录最小值是否改变过,如果没有改变,则后面就不需要交换
//其实也没有必要设置exc变量来记录,可以使用pos的值来判定,如果没有交换过,那么pos的值为-1;
for(int j = i;j<arr.length;j++){
if(min>arr[j]){
min = arr[j];
pos = j;
exc = true;
}
}
if(exc){
int temp = arr[i];
arr[i] = arr[pos];
arr[pos] = temp;
}
}
}

插入排序算法:

算法描述:

  1. 从第一个元素开始,该元素可以认为已经被排序;
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
  5. 将新元素插入到该位置;

    重复步骤2~5。

排序方式:in-place

时间复杂度:

  • 最佳情况:T(n) = O(n)
  • 最坏情况:T(n) = O(n2)
  • 平均情况:T(n) = O(n2)

    额外空间复杂度:O(1)

    代码实现:
/*******Insert Sort algorithm **************/
public void insert(int[] arr){//直接插入排序
for(int i=1;i<arr.length;i++) {//从第二个元素开始
//pVal 用来记录当前元素的值,因为在移动元素时,会把当前元素的值给覆盖掉。
int pVal = arr[i];
int j = i-1;
while(pVal < arr[j]) {//后移元素
arr[j+1] = arr[j];
j--;
}
arr[j+1] = pVal;//找到合适位置后把当前元素插入到合适位置
}
}

希尔排序

算法描述:

希尔排序的基本步骤:

选择增量 :gap=length/2,缩小增量:gap = gap/2

增量序列:用序列表示增量选择,{n/2, (n/2)/2, …, 1}

希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;

按增量序列个数k,对序列进行k趟排序;

每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序;

仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

排序方式:in-place

时间复杂度:

  • 最佳情况:T(n) = O(n)
  • 最坏情况:T(n) = O(n2)
  • 平均情况:T(n) =O(n1.3)

    空间复杂度:O(1)

代码实现:

/*******Shell Sort algorithm **************/
public void shell(int[] arr) {
int gap = 1;//定义步长
while(gap<arr.length/3)//动态计算步长
gap=gap*3+1; for(;gap>0;gap=(int)Math.floor(gap/3)) {
for(int i = gap;i<arr.length;i++) {
int temp = arr[i];
int j = i-gap;
//直接插入排序
for(;j>0 && arr[j]>temp;j-=gap) {
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
}
}

归并排序:

把长度为n的输入序列分成两个长度为n/2的子序列;

对这两个子序列分别采用归并排序;

将两个排序好的子序列合并成一个最终的排序序列。

排序方式:out-place

时间复杂度:

  • 最佳情况:T(n) = O(nlog n)
  • 最差情况:T(n) = O(nlog n)
  • 平均情况:T(n) = O(nlog n)

    空间复杂度:O(n)

    代码描述:
/*******Merge Sort algorithm **************/
//先实现把两个有序数组合并成一个有序数组的函数
public int[] merge(int[] l,int[] r) {
int[] res=new int[l.length+r.length];
int i=0,j=0,k=0;
while(i<l.length && j<r.length) {
if(l[i]<r[j]) {
res[k++]=l[i++];
}else {
res[k++]=r[j++];
}
}
while(i<l.length)
res[k++]=l[i++];
while(j<r.length)
res[k++]=r[j++];
return res;
} //下面来写归并排序,利用递归
public int[] mergeSort(int[] arr) {
if(arr.length < 2)//定义递归出口
return arr;
int mid = (int)Math.floor(arr.length/2);
int[] l = new int[mid];
int[] r = new int[arr.length-mid];
int lk = 0;
int rk = 0;
for(int i=0;i<mid;i++) {
l[lk++] = arr[i];
}
for(int i=mid;i<arr.length;i++) {
r[rk++] = arr[i];
}
return merge(mergeSort(l),mergeSort(r));
}

快速排序算法:

算法描述:

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。

  1. 从数列中挑出一个元素,称为 “基准”(pivot),即枢纽元;
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边),在这个分区退出之后,该基准就处于数列的中间位置,称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

排序方式:in-place

时间复杂度:

最佳情况:T(n) = O(nlog n)

最差情况:T(n) = O(n2)

平均情况:T(n) = O(nlog n)

空间复杂度:

平均:O(log n)

最差: O(n)

代码实现:

/***********Quick Sort*********************/
public void quickSort(int[] arr,int l,int r) {
if(l>=r) return;//设置递归出口
int pivot = arr[l];//设置标准枢轴量
int low = l;
int high = r;
while(low<high) {
while(low<high && arr[high]>pivot) high-=1;
arr[low] = arr[high];
while(low<high && arr[low]<=pivot) low+=1;
arr[high] = arr[low];
}
arr[low] = pivot; quickSort(arr, l, low-1);
quickSort(arr, low+1, r);
}

以上经典排序算法的总结:

算法名称 平均时间复杂度 最好情况 最坏情况 空间复杂度 排序方式 稳定性
冒泡排序 O(n^2) O(n) O(n^2) O(1) IN Y
选择排序 O(n^2) O(n^2) O(n^2) O(1) IN N
插入排序 O(n^2) O(n^2) O(n^2) O(1) IN Y
Shell 排序 O(nlogn) O(n(logn)^2) O(n(logn)^2) O(1) IN N
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) OUT Y
快排 O(nlogn) O(nlogn) O(n^2) O(logn) IN N

Java 中常见排序算法的更多相关文章

  1. Java中的排序算法(2)

    Java中的排序算法(2) * 快速排序 * 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists). * 步骤为: * 1. 从数 ...

  2. Java实现常见排序算法

    常见的排序算法有冒泡排序.选择排序.插入排序.堆排序.归并排序.快速排序.希尔排序.基数排序.计数排序,下面通过Java实现这些排序 1.冒泡排序 package com.buaa; import j ...

  3. JS中常见排序算法详解

    本文将详细介绍在JavaScript中算法的用法,配合动图生动形象的让你以最快的方法学习算法的原理以及在需求场景中的用途. 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements Java ...

  4. Java中各种排序算法

    package org.rut.util.algorithm.support; import org.rut.util.algorithm.SortUtil; /** * @author treero ...

  5. Java基础语法(8)-数组中的常见排序算法

    title: Java基础语法(8)-数组中的常见排序算法 blog: CSDN data: Java学习路线及视频 1.基本概念 排序: 是计算机程序设计中的一项重要操作,其功能是指一个数据元素集合 ...

  6. 常见排序算法(附java代码)

    常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...

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

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

  8. 常见排序算法题(java版)

    常见排序算法题(java版) //插入排序:   package org.rut.util.algorithm.support;   import org.rut.util.algorithm.Sor ...

  9. Java中的经典算法之选择排序(SelectionSort)

    Java中的经典算法之选择排序(SelectionSort) 神话丿小王子的博客主页 a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕.也就是:每一趟 ...

随机推荐

  1. 8.Java的特性和优势

    简单性:可以说Java是C++语法的纯净版,没有头文件,没有指针运算,也不用分配内存. 面向对象:是一种程序设计技术,它将重点放在对象以及对象的接口上,模拟人的思维写程序,所以人去学习非常快.因此,J ...

  2. CentOS7 搭建Fabric 1.0

    1.环境搭建 1.1 go的按装及配置 1.1.1下载go压缩包 ​ wget https://dl.google.com/go/go1.9.2.linux-amd64.tar.gz 1.1.2 解压 ...

  3. Java入门 - 高级教程 - 08.Applet

    原文地址:http://www.work100.net/training/java-applet.html 更多教程:光束云 - 免费课程 Applet 序号 文内章节 视频 1 概述 2 Apple ...

  4. xsd 和 wsdl

    xsd : 可用方便 不同的语言之间的 用命令行来 转换对应语言的. wsdl: 可用方便不同语言的类描述 用命令行 来相互转换. 类似 thift me ?

  5. c#数字图像处理(三)灰度直方图

    灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数.如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数). using System; using Syst ...

  6. zerotier 远程办公方案

    武汉新肺炎疫情下,搞得人心惶惶.很多公司都要求前期远程办公 我厂日常有在家远程应急支持的情况,所以公司很早就有VPN服务.只需要申请VPN服务,开通之后就可以连上公司各种公共资源. 然而对于一些非公共 ...

  7. JavaScript面向对象:创建对象

    1.初级创建对象 var oCar=new Object; oCar.color='red'; oCar.door=4; oCar.map=3; oCar.showColor=function () ...

  8. 什么是ip地址、子网掩码、网关和DNS?

    什么是ip地址? IP是32位二进制数据,通常以十进制表示,并以“.”分隔.IP地址是一种逻辑地地址,用来标识网络中一个个主机,IP有唯一性,即每台机器的IP在全世界是唯一的. IP地址=网络地址+主 ...

  9. C语言创建文件夹

    问题需求:在程序中需要使用文件夹时,一般可以先在程序目录或某一路径下创建一个文件夹,然后使用该文件夹. 这种方法比较麻烦,需提前创建文件夹. 使用C语言创建文件夹的代码可以如下: #include & ...

  10. Java的变量与常量

    常量: 在程序运行期间,固定不变得量. 常量的分类: 字符串常量:凡是用双引号引起来的部分,叫做字符串常量.例如:“abc”.“Hello”.“123”. 整数常量:直接写上的数字,没有小数点.例如: ...