Arrays.sort() 采用了2种排序算法 -- 基本类型数据使用快速排序法,对象数组使用归并排序.

java的Collections.sort算法调用的是归并排序,它是稳定排序

方法一:直接插入

1.基本思路:

在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

2.代码实现:

(1)首先设定插入次数,即循环次数,for(int i=1;i

(2)设定插入数和得到已经排好序列的最后一个数的位数。temp和j=i-1。

(3)从最后一个数开始向前循环,如果插入数小于当前数,就将当前数向后移动一位。

(4)将当前数放置到空着的位置,即j+1。

public static void insertSort(int[] data){inttemp;for(int i=1;i

temp=data[i];intj;for(j =i-1;j>=0;j--){//从第i-1的位置上开始比较if(data[j]>temp){//若前面的数大,则往后挪一位

data[j+1] =data[j];

}else{break;//否则,说明要插入的数比较大

}

}

data[j+1] =temp;//找到这个位置,插入数据

}

}

3.时间复杂度和空间复杂度:

直接插入排序的平均复杂度为O(n²),最坏时间复杂度:O(n²),空间复杂度:O(1),没有分配内存。

方法二:希尔排序

1.定义:

针对直接插入排序的下效率问题,有人对次进行了改进与升级,这就是现在的希尔排序。希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

2.基本思路:

数的个数为length,i=length/2,将下标差值为i的数分为一组,构成有序序列。

再取i=i/2 ,将下标差值为i的数分为一组,构成有序序列。

重复第二步,直到k=1执行简单插入排序。

思路

(1)希尔排序(shell sort)这个排序方法又称为缩小增量排序,是1959年D·L·Shell提出来的。该方法的基本思想是:设待排序元素序列有n个元素,首先取一个整数increment(小于n)作为间隔将全部元素分为increment个子序列,所有距离为increment的元素放在同一个子序列中,在每一个子序列中分别实行直接插入排序。然后缩小间隔increment,重复上述子序列划分和排序工作。直到最后取increment=1,将所有元素放在同一个子序列中排序为止。

(2)由于开始时,increment的取值较大,每个子序列中的元素较少,排序速度较快,到排序后期increment取值逐渐变小,子序列中元素个数逐渐增多,但由于前面工作的基础,大多数元素已经基本有序,所以排序速度仍然很快。

(3)希尔排序举例:

3.代码实现:

(1)首先确定每一组序列的下标的间隔,循环每次需要的间隔:int i = length/2; i >0 ; i /= 2

(2)然后将每一组序列中元素进行插入排序,第二组第一个插入的数字是第一组第一个插入数字之后的那个数组,从i之后每个数字都要进行插入排序,就是插入的序列是各自不同的序列,不是一个一个子序列循环,而是在一个循环中for (int j=i;j

(3)直到i=0为止。

public static void shellSort(int[] array){int length =array.length;for (int i = length/2; i >0 ; i /= 2) {//序列的间隔,一直到间隔为一,这时候就只有一个子序列

for (int j=i;j

int temp = array[j];//里面就是直接插入算法

intk;for(k = j-i; k>=0;k -= i){//实现各个数字插入排序到不同的序列中,直到间隔为1的时候,只有一个序列,就是完全的一个直接插入排序

if(temp

array[k+i] =array[k];

}else{break;

}

}

array[k+i] = temp;//把数字插入到位置上

}

}

System.out.println(Arrays.toString(array));

}

4.时间复杂度和空间复杂度:

希尔排序的平均时间复杂度为O(n²),空间复杂度O(1) 。

方法三:简单选择

1.基本思路:

基本原理如下:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录的位置与第一个记录的位置交换;接着对不包括第一个记录以外的其他记录进行第二次比较,得到最小记录并与第二个位置记录交换;重复该过程,知道进行比较的记录只剩下一个为止。

2.代码实现:

(1)确定要插入最小值的位置,从0开始到最后int i = 0; i

(2)将每次开始位置上的数字暂定为最小值min,从开始数字之后一个个和min比较,再把最小值存放到min

(3)将最小值所在位置上的数字和开始位置上的数字交换

public static void selectSort(int[] array){int len =array.length;for (int i = 0; i

int min = array[i];//设定开始数字为最小的值最小值

int flag =i;for(int j=i+1;j

if(min>array[j]){

min=array[j];

flag=j;

}

}if(flag !=i){

array[flag]=array[i];

array[i]=min;

}

}

}

3.时间复杂度:

简单选择排序时间复杂度:O(n^2)

方法四:堆排序

1.基本思路:

(1)若array[0,...,n-1]表示一颗完全二叉树的顺序存储模式,则双亲节点指针和孩子结点指针之间的内在关系如下:

任意一节点指针 i:父节点:i==0 ? null : (i-1)/2

左孩子:2*i + 1

右孩子:2*i + 2

(2)堆的定义:n个关键字序列array[0,...,n-1],当且仅当满足下列要求:(0 <= i <= (n-1)/2)

① array[i] <= array[2*i + 1] 且 array[i] <= array[2*i + 2]; 称为小根堆;

② array[i] >= array[2*i + 1] 且 array[i] >= array[2*i + 2]; 称为大根堆;

(3)建立大根堆:

n个节点的完全二叉树array[0,...,n-1],最后一个节点n-1是第(n-1-1)/2个节点的孩子。对第(n-1-1)/2个节点为根的子树调整,使该子树称为堆。

对于大根堆,调整方法为:若【根节点的关键字】小于【左右子女中关键字较大者】,则交换。

之后向前依次对各节点((n-2)/2 - 1)~ 0为根的子树进行调整,看该节点值是否大于其左右子节点的值,若不是,将左右子节点中较大值与之交换,交换后可能会破坏下一级堆,于是继续采用上述方法构建下一级的堆,直到以该节点为根的子树构成堆为止。

反复利用上述调整堆的方法建堆,直到根节点。

(4)堆排序:(大根堆)

①将存放在array[0,...,n-1]中的n个元素建成初始堆;

②将堆顶元素与堆底元素进行交换,则序列的最大值即已放到正确的位置;

③将数组中array[0,...,n-1]前n-1个元素再次形成大根堆,再重复第②③步,直到堆中仅剩下一个元素为止。

2.代码实现:

public static int[] buildMaxHeap(int[] array,int length){//截取数组从0到length,构建大根堆

for (int i = (length-2)/2; i >=0 ; i--) {//从最后一个有子结点的结点开始调整,(减一)一直调节到根节点

adjustDownToUp(array,i,length);

}returnarray;

}private static void adjustDownToUp(int[] array, int i, int length) {//i要调整的结点

int temp =array[i];//int j = i*2+1;//取得左孩子

for (int j=i*2+1;j

j++;//取更大结点的索引

}if(temp

array[i] = array[j];//调整根节点的值为最大值

i=j;//把空余的位置给i//array[j] = temp;

}

}

array[i]= temp;//找到最后空余的位置,填上向下调整的值

}public static void heapSort(int[] array){int len =array.length;inttemp;for (int i = len; i >0; i--) {

array=buildMaxHeap(array,i);

temp= array[0];

array[0] = array[i-1];

array[i-1]=temp;

}

System.out.println(Arrays.toString(array));

}

3.时间复杂度:

时间复杂度:建堆:o(n),每次调整o(log n),故最好、最坏、平均情况下:o(n*logn);

方法五:冒泡排序

1.基本思路:

一次冒泡将序列中从头到尾所有元素两两比较,将最大的放在最后面。

将剩余序列中所有元素再次两两比较,将最大的放在最后面。

重复第二步,直到只剩下一个数。

2.代码实现:

public static void bubbleSort(int[] array){

for (int i = 0; i

for (int j = 0; j

int temp = array[j];

if(array[j]>array[j+1]){

array[j]=array[j+1];

array[j+1]=temp;

}

}

}

}

3.时间复杂度:

冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1),它是一种稳定的排序算法。

方法六:快排

1.基本思路:

快速排序使用分治策略来把一个序列(list)分为两个子序列(sub-lists)。步骤为:

从数列中挑出一个元素,称为"基准"(pivot)。

重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

2.代码实现:

public static void quickSprt(int[] array,int low,inthigh){if(low>=high) return;int left =low;int right =high;int pivot = array[left];//设立基准点

while (leftpivot)//从右向左,大数位置不变

right--;

array[left]= array[right];//把小数移到左边

while (left < right && array[left]

left++;

array[right]= array[left];//把大数移到右边

}

array[left]=pivot;

quickSprt(array,low,left-1);

quickSprt(array,left+1,high);

}

3.时间复杂度:

虽然 快排的时间复杂度达到了 O(n²),但是在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好。

方法七:归并排序

1.基本思路:

对于给定的一组记录,利用递归与分治技术将数据序列划分成为越来越小的半子表(直到剩余一个数字),在对半子表排序,最后再用递归方法将排好序的半子表合并成为越来越大的有序序列。

(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置

(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

(4)重复步骤3直到某一指针达到序列尾

(5)将另一序列剩下的所有元素直接复制到合并序列尾

2.代码实现:

//归并排序

public static int[] mergeSort(int[] array,int low,inthigh){if(low

mergeSort(array,low,mid);

mergeSort(array,mid+1,high);

merge(array,low,mid,high);//归并

}returnarray;

}private static void merge(int[] array, int low, int mid, inthigh) {int i = low;//指针,前一个序列的头指针

int j = mid+1;//指针,后一个序列的头指针

int[] temp = new int[high-low+1];int k=0;while (i<=mid && j<=high){if (array[i]

temp[k++] = array[i++];//前一个序列指针后移一位

}else{

temp[k++] = array[j++];//后一个序列指针后移一位

}

}//最后只会剩下一组序列

while (i<=mid){

temp[k++] = array[i++];//把前一个指针剩余的数字放入临时数组

}while (j<=high){

temp[k++] = array[j++];//把后一个指针剩余的数字放入临时数组

}for (int m = 0; m

array[low+m] =temp[m];

}

}

3.时间复杂度:

时间复杂度:O(nlog2n)

方法八:基数排序

1.基本思路:

(1)按照所有的数的个位数,在0---9 的基数序列中,把各个数字排入,每一个数字基数上也是一个序列。

(2)将新序列取出按基数顺序取出,形成新数组。

(3)再按照十位数字进行排序,插入到基数序列,循环(1)(2)

2.代码实现:

public static void baseSort(int[] array){

ArrayList> queue = new ArrayList>();for (int i = 0; i <10 ; i++) {

ArrayList queue2 = new ArrayList();

queue.add(queue2);//创建一个基数从0---9 每个数字上都是一个list

}//找到最大值,并判断最大值是几位数

int max = array[0];for (int i = 1; i < array.length; i++) {if(max

max=array[i];

}

}int time = 0;while(max>0){

max/= 10;

time++;

}for (int i = 0; i < time; i++) {//循环每一个位数(个位、十位、百位)

for (int j = 0; j

int x = array[j] % (int)Math.pow(10,i+1) / (int)Math.pow(10,i);

ArrayList queue3 =queue.get(x);;

queue3.add(array[j]);

queue.set(x,queue3);

}int count = 0;for (int k = 0; k < 10; k++) {while (queue.get(k).size() > 0) {

ArrayList queue4 =queue.get(k);

array[count]= queue4.get(0);

queue4.remove(0);

count++;

}

}

}

}

3.时间复杂度:

时间复杂度:O(nlog2n)

总结:

排序算法

思路

排序算法

最好时间复杂度

平均时间复杂度

最坏时间复杂度

空间复杂度

(辅助存储)

是否稳定

插入排序

将一个数字插入已经排列好的序列中

直接插入法

O(N)

O(N2)

O(N2)

O(1)

稳定

希尔排序

O(N)

O(N1.3)

O(N2)

O(1)

不稳定

选择排序

每一次循环都是选择出最小(最大)的数字放到数组最前面(最后面)的位置

简单选择

O(N)

O(N2)

O(N2)

O(1)

不稳定

堆排序

O(N*log2N)

O(N*log2N)

O(N*log2N)

O(1)

不稳定

交换排序

(冒泡)两两交换,大的后移,再次两两交换

(快速)和基准交换,比基准大排右边,比基准小排左边

冒泡排序

O(N)

O(N2)

O(N2)

O(1)

稳定

快速排序

O(N*log2N)

O(N*log2N)

O(N2)

O(log2n)~O(n)

不稳定

归并排序

O(N*log2N)

O(N*log2N)

O(N*log2N)

O(n)

稳定

基数排序

O(d(r+n))

O(d(r+n))

O(d(r+n))

O(rd+n)

稳定

八大排序算法java_java实现八大排序算法相关推荐

  1. des算法java_Java加密算法笔记--DES算法实现

    Java加密算法笔记--DES算法实现 在使用中发现,经过加密的字符串如果要进行传输,需要使用Base64进行编码,这样能保证加密信息的完整性,确保将来解密成功. import java.securi ...

  2. 算法 经典的八大排序算法详解和代码实现

    算法 经典的八大排序算法详解和代码实现 排序算法的介绍 排序的分类 算法的时间复杂度 时间频度 示例 图表理解时间复杂度的特点 时间复杂度 常见的时间复杂度 空间复杂度 排序算法的时间复杂度 冒泡排序 ...

  3. 八大排序的思想讲解与排序算法可视化

      可视化的动图可以帮助我们理解排序算法,在了解了排序算法的思想后,观察动图可以加深我们对排序算法的理解.   本文全部代码已上传Gitee. 文章目录 一.插入排序 1.直接插入排序 2.希尔排序 ...

  4. 归并排序改良 java_Java 八种排序算法总结

    image 前言 好久没复习基础了,写个冒泡排序都要想一会.感觉自己好像老了好多,今天手痒总结一下排序算法.目前网上博客普遍都有详细介绍,写的很清楚.说实话我是没必要再写一遍的,感觉就是在啰嗦.还是重 ...

  5. 图码详解算法|理解八大思想,胜刷百道力扣!

    文章首发:微信搜索「Kevin的学堂」 零.前言 Hello,我是Kevin,之前和大家刷题打卡了很多天,但是发现效果并不理想,于是我在反思,我知道由于我追求数量导致了文章质量不高,另外我只是分享题解 ...

  6. c语言数组排序算法的实验总结,排序算法实验报告技术总结.doc

    数据结构实验报告八种排序算法实验报告 实验内容编写关于八种排序算法的C语言程序,要求包含直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序.实验步骤 各种内部排序算法 ...

  7. java排序 面试题_Java八大排序(面试答题!)

    八大排序(重点!!) ​排序算法大体可分为两种: 1.比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等. 2.非比较排序,时间 ...

  8. java 基础算法教程ppt,基础排序算法(附加java实现)

    七种最基本的排序算法:(面试必会!) 冒泡排序: 最基础的排序算法,从数列最前端开始,两两比较,如果前一个数比后一个数大,那么两个数就交换位置,经过一轮遍历之后,最大的数就到了数列的最后一个位置上,再 ...

  9. 算法系列【希尔排序】篇

    常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等.用一张图概括: 关于时间复杂度: 1.     平方阶 (O(n2)) 排序各类简单排序:直接插入 ...

最新文章

  1. C#与Excel互操作
  2. bigtall的敏捷日记(1)
  3. 爆料!传阿里人靠脸吃饭真相是......
  4. jquery学习手记(10)事件简介
  5. Tomcat【环境搭建 02】Web端403 Access Denied You are not authorized to view this page解决方法(Tomcat 10.2.12 版本)
  6. C++pair对组的创建
  7. Mybatis foreach遍历
  8. 【Mac】setremotelogin: Turning Remote Login on or off requires Full Disk Access privileges.
  9. 深度评测阿里云、百度云、腾讯云和华为云
  10. 数据分析师熬夜整理:最全「零售业」数据指标和使用技巧
  11. 指针知识(四):指针数学计算
  12. 只需订阅“全部文章”专栏便可查看所有文章
  13. zepto 自定义打包
  14. java导入jdk源码_eclipse导入JDK源码
  15. 博途wincc 与 sql 连接操作(博途V14 wincc advanced)
  16. 异常与调试之SEH、UEH、VEH、VCH以及SEH的区别总结——简单好理解
  17. 棋盘分割(区间DP)
  18. 第1140期AI100_机器学习日报(2017-11-01)
  19. 「WinddowInsets(二)」我们能用WindowInsets做什么?
  20. 强智科技教务系统学科成绩c语言,湖南强智科技教务系统python模拟登录并爬取成绩(财院)...

热门文章

  1. String最大长度是多少?涉及知识面太多,不要错过!
  2. 基于ssm的模糊查询,解决中文乱码后可查询中文关键字
  3. PS4怪物猎人世界服务器稳定吗,《怪物猎人世界》PS4/PS4 Pro运行对比 游戏帧数不稳定...
  4. 成立一家公司,你需要做什么?
  5. golang xorm mysql_golang xorm mysql代码生成器
  6. 【无标题】呵呵没事的
  7. Redis缓存三大问题
  8. html/css使文字图片div在整个网页上居中(水平居中+垂直居中)transform属性配置
  9. react中的 PropTypes使用
  10. 海贼OJ并查集练习题:朋友圈