常见的排序算法之Java代码解释
一 简要介绍
算法思路,从后往前先找到要插入的位置,如果小于则就交换,将元素向后移动,将要插入数据插入该位置即可。时间复杂度为O(n2),空间复杂度为O(1)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package sort.algorithm;public class DirectInsertSort { public static void main(String[] args) { // TODO Auto-generated method stub int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 }; int temp, j; for (int i = 1; i < data.length; i++) { temp = data[i]; j = i - 1; // 每次比较都是对于已经有序的 while (j >= 0 && data[j] > temp) { data[j + 1] = data[j]; j--; } data[j + 1] = temp; } // 输出排序好的数据 for (int k = 0; k < data.length; k++) { System.out.print(data[k] + " "); } }} |
如果mid小于data,则就表示插入的数据在mid的右边,low=mid+1
最后整体进行右移操作。
时间复杂度O(n2),空间复杂度O(1)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package sort.algorithm;//折半插入排序public class HalfInsertSort { public static void main(String[] args) { int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 }; // 存放临时要插入的元素数据 int temp; int low, mid, high; for (int i = 1; i < data.length; i++) { temp = data[i]; // 在待插入排序的序号之前进行折半插入 low = 0; high = i - 1; while (low <= high) { mid = (low + high) / 2; if (temp < data[mid]) high = mid - 1; else // low=high的时候也就是找到了要插入的位置, // 此时进入循环中,将low加1,则就是要插入的位置了 low = mid + 1; } // 找到了要插入的位置,从该位置一直到插入数据的位置之间数据向后移动 for (int j = i; j >= low + 1; j--) data[j] = data[j - 1]; // low已经代表了要插入的位置了 data[low] = temp; } for (int k = 0; k < data.length; k++) { System.out.print(data[k] + " "); } }} |
算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package sort.algorithm;public class ShellSort { public static void main(String[] args) { int a[] = { 1, 54, 6, 3, 78, 34, 12, 45, 56, 100 }; double d1 = a.length; int temp = 0; while (true) { //利用这个在将组内倍数减小 //这里依次为5,3,2,1 d1 = Math.ceil(d1 / 2); //d为增量每个分组之间索引的增量 int d = (int) d1; //每个分组内部排序 for (int x = 0; x < d; x++) { //组内利用直接插入排序 for (int i = x + d; i < a.length; i += d) { int j = i - d; temp = a[i]; for (; j >= 0 && temp < a[j]; j -= d) { a[j + d] = a[j]; } a[j + d] = temp; } } if (d == 1) break; } for (int i = 0; i < a.length; i++) System.out.print(a[i]+" "); }} |
五 交换类排序之冒泡排序
时间复杂度O(n2),空间复杂度O(1)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package sort.algorithm;//冒泡排序:是一种交换排序public class BubbleSort { // 按照递增顺序排序 public static void main(String[] args) { // TODO Auto-generated method stub int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20, 13, 100, 37, 16 }; int temp = 0; // 排序的比较趟数,每一趟都会将剩余最大数放在最后面 for (int i = 0; i < data.length - 1; i++) { // 每一趟从开始进行比较,将该元素与其余的元素进行比较 for (int j = 0; j < data.length - 1; j++) { if (data[j] > data[j + 1]) { temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; } } } for (int i = 0; i < data.length; i++) System.out.print(data[i] + " "); }} |
空间复杂度O(long2n),快速排序需要递归用到了栈
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package sort.algorithm;//快速排序算法:是一种交换排序public class QuikSort { public static void main(String[] args) { // TODO Auto-generated method stub int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20, 105, 34, 44, 19 }; QuikSort sort = new QuikSort(); sort.sortArray(data, 0, data.length - 1); for (int i = 0; i < data.length; i++) System.out.print(data[i] + " "); } // 这里不用返回值,直接对传入的数组进行操作 public void sortArray(int data[], int first, int end) { int temp; int i = first, j = end; if (first < end) { temp = data[i]; // 当i=j的时候,则说明扫描完成了 while (i < j) { // 从右边向左边扫描找到一个小于temp的元素 while (j > i && data[j] > temp) j--; if (i < j) { // 将该元素赋值给temp data[i] = data[j]; // 赋值后就应该将i+1指向下一个序号 i++; } // 然后从左边向右边开始扫描,找到一个大于temp的元素 while (i < j && temp > data[i]) i++; if (i < j) { // 将该元素赋值给temp data[j] = data[i]; // 赋值后就应该将j-1指向前一个序号 j--; } } // 将轴数据放在i位置中 data[i] = temp; sortArray(data, first, i - 1); sortArray(data, i + 1, end); } }} |
简单选择排序,每一趟从数据中选择一个最小值放到最前面,但是不需要交换位置,只记录该交换的位置,只有找到后才做一次交换!
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package sort.algorithm;//简单选择排序:是一种选择排序public class SelectSort { public static void main(String[] args) { // TODO Auto-generated method stub int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20, 11, 3, 1, 100, 89 }; int temp, k; // 开始时间 long start = System.nanoTime(); // 选择的每一趟数,每一趟都会将一个最小的放在最前面。 for (int i = 0; i < data.length - 1; i++) { // 使用k来记录要交换的位置,且k在比较的过程不断变化 k = i; // 由于每一趟都会将最小的放在最前面,所以索引+1 for (int j = i; j < data.length; j++) // 这里始终要与k比较 if (data[j] < data[k]) k = j; // k已经存放了交换的位置了 temp = data[i]; data[i] = data[k]; data[k] = temp; } System.out.println(System.nanoTime() - start); // 输出排序好的数据 for (int m = 0; m < data.length; m++) { System.out.print(data[m] + " "); } }} |
八 选择类排序之堆排序
堆排序就是建立大顶堆或者小顶堆,若建立大顶堆,每次对于建好的大顶堆将根元素与最后一个元素交换,无序的数目减少,有序的数目增加。
对于求N个数据中的前n个最小的数据,首先就是建立一个n个的大顶堆,然后让其余的元素来进行与这堆顶元素比较,如果小于则与堆顶互换元素。
这里采用数组存储节点,并且下标统一从0,length-1,所以对于这样处理的左孩子节点下标为
2 * i+1,右孩子的节点下标为2 * i+2
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package sort.algorithm;public class HeapSort { public static int heap_size; // 左孩子编号 public static int leftChild(int i) { return 2 * i+1; } // 右孩子编号 public static int rightChild(int i) { return 2 * i + 2; } /** * 保持最大堆的性质 * 堆中的数组元素 * 对以该元素为根元素的堆进行调整,假设前提:左右子树都是最大堆 * 由于左右孩子都是最大堆,首先比较根元素与左右孩子,找出最大值,假如大于根元素,则调整两个元素的值; * 由于左孩子(右孩子)的值与根元素交换,有可能打破左子树(右子树)的最大堆性质,因此继续调用,直至叶子元素。 */ public static void max_heapify(int[] a, int i) { int left = leftChild(i); int right = rightChild(i); int largest = 0; if (left < heap_size && a[i] < a[left]) { largest = left; } else { largest = i; } if (right < heap_size && a[right] > a[largest]) { largest = right; } if (largest == i) { return; } else { int temp = a[i]; a[i] = a[largest]; a[largest] = temp; max_heapify(a, largest); } } /** * 建立最大堆。在数据中,下标a.length/2+1一直到最后的元素a.length-1都是叶子元素 * 因此从其前一个元素开始,一直到 * 第一个元素,重复调用max_heapify函数,使其保持最大堆的性质 */ public static void build_max_heap(int[] a) { //从0~a.length/2中建立最大堆 for (int i = a.length / 2; i >= 0; i--) { max_heapify(a, i); } } /** * 堆排序:首先建立最大堆,然后将堆顶元素(最大值)与最后一个值交换,同时使得 堆的长度减小1 * 调用保持最大堆性质的算法调整,使得堆顶元素成为最大值,此时最后一个元素已被排除在外、 */ public static void heapSort(int[] a) { //构建最大堆 build_max_heap(a); for (int i = a.length - 1; i >= 0; i--) { //将第一个元素和最后一个元素进行互换 int temp = a[0]; a[0] = a[i]; a[i] = temp; heap_size--; //调整堆为最大堆 max_heapify(a, 0); } } public static void main(String[] args) { int a[] = {5, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7}; heap_size = a.length;//最大数 heapSort(a); //输出结果 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } }} |
九 二路归并排序
归并排序主要分为分割和归并,每次分割后,对于每一个部分进行排序,然后进行归并,建立一个临时表存储归并后的结果,在将两路进行归并的时候,每一路都已经是有序的。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package sort.algorithm;import java.util.Arrays;//二路归并排序主要分为//分割和合并public class MergeSort { public static void main(String[] args) { int data[] = { 2, 6, 10, 3, 9, 80, 1, 16, 27, 20 }; mergeSort(data,0,data.length-1); //直接打印 System.out.println(Arrays.toString(data)); } //二路归并的分割处理 public static void mergeSort(int[] array,int start,int end) { if(start<end) { //划分为两部分,每次两部分进行归并 int mid=(start+end)/2; //两路归并 //先递归处理每一个部分 mergeSort(array,start,mid); mergeSort(array,mid+1,end); //然后将已经排序好的,两两归并排序再进行合并处理 merge(array,start,mid,mid+1,end); } } //二路归并两个部分的时候进行排序 public static void merge(int[] array,int start1,int end1,int start2,int end2) { int i=start1;//左路起始索引 int j=start2;//右路起始索引 int k=0; //归并的时候,会将两个数组数据按照大小输入到一个临时数组中 //建立临时长度为两个子列表长度的数组 int[] temp=new int[end2-start1+1]; //循环遍历,按顺序找出两个表中的最小数据依次放入临时表中 //注意此时左路和右路已经是有序的了。 //当一路有一个小的,则会索引加1,继续喝另外一路的上次索引进行比较 while(i<=end1&&j<=end2) { //这里确定归并的次序大小 if(array[i]>array[j]) temp[k++]=array[j++]; else temp[k++]=array[i++]; } //把剩下的元素放入临时数组中,只有一路的 while(i<=end1) temp[k++]=array[i++]; while(j<=end2) temp[k++]=array[j++]; k=start1; for(int item:temp) array[k++]=item; }} |
十 各种排序总结:
本文出自 “在云端的追梦” 博客,请务必保留此出处http://computerdragon.blog.51cto.com/6235984/1161859
常见的排序算法之Java代码解释的更多相关文章
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
- 一遍记住 8 种排序算法与 Java 代码实现
☞ 程序员进阶必备资源免费送「21种技术方向!」 ☜ 作者:KaelQ, www.jianshu.com/p/5e171281a387 1.直接插入排序 经常碰到这样一类排序问题:把新的数据插入到已经 ...
- 八大排序算法的Java代码实现
简单插入排序 public class QuickSort { private static void quickSort(int [] a, int low, int high){ if (low ...
- java讲讲几种常见的排序算法(二)
java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...
- java讲讲几种常见的排序算法
java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...
- 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)
排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...
- Java实现常见的排序算法
一.排序算法 常见的排序算法主要分为下面几类: 选择排序 堆排序 冒泡排序 快速排序 插入排序 希尔排序 归并排序 桶式排序 基数排序 本文主要介绍选择排序.堆排序.冒泡排序.快速排序和归并排序的原理 ...
- 常见排序算法总结 -- java实现
常见排序算法总结 -- java实现 排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间 ...
- java编程之常见的排序算法
java常见的排序算法 第一种:插入排序 直接插入排序 1, 直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的 ...
随机推荐
- sicily 1022. Train Problem
本题主要是出栈入栈顺序的问题 Home Problems My Status Standing <-> 1022. Train Problem Total: 2 ...
- 数字图象处理MATLAB学习
diagram = imread('C:\Users\Administrator\Desktop\Compressed\fiter\lena256.jpg') %diagram = rgb2gray( ...
- callback调用测试
<html> <head> <script> var context="全局"; var testObj={ context:"初始& ...
- win7局域网无法ping通本机的问题解决方法
对于window7系统,很多朋友会发现:默认下是不允许被ping的,其实都系统自带的防护墙所阻止了,新建一个策略就可以实现被ping通,如下操作
- 浅析php fwrite写入txt文件的时候用 \r\n不能换行的问题
以下是对php中fwrite写入txt文件的时候用 \r\n不能换行的问题进行了介绍,需要的朋友可以过来参考下今天遇到了一个问题就是用fwrite写入txt文件的时候用 rn不能换行试了很久都没找到办 ...
- Android中表示尺寸的六种度量单位
本文章来自:http://my.eoe.cn/lakeside/archive/4831.html in:Inches - 表示英寸,是屏幕的物理尺寸,每英寸等于2.54厘米.平时说手机屏幕4(英)寸 ...
- apache common包下的StringUtils的join方法
apache common包下的StringUtils的join方法: 关键字:java string array join public static String join(Iterator it ...
- XAML 概述三
通过对前面2节对XAML的介绍,我们对XAML有了一定的认识.这一节我们来简单了解一下部分XAML命名空间(x:)语言功能. x命名空间映射的是http://schemas.microsoft.com ...
- nodejs fs 模块的用途
/*** New node filefs 操作*/var fs = require(“fs”); /*创建文件 var fileName = “anps_hsj”;fs.mkdir(fileName, ...
- JAVA算术运算符、关系运算符和位运算符
算术运算符 1.java的算数运算符包括+(加).-(减).*(乘)./(除).%(取余),在运算过程中出现的隐式转换原则和C语言一样:2. 高位数据向低位数据转化要使用强制转化: 关系运算符 1.j ...