目录
1 冒泡排序1.1 代码1.2 复杂性及稳定性分析
2 选择排序2.1 代码2.2 复杂性及稳定性分析
3 插入排序3.1 代码3.2 复杂性及稳定性分析
4 希尔排序4.1 代码4.2 复杂性及稳定性分析
5 归并排序5.1 代码5.2 复杂性及稳定性分析
6 快速排序6.1 代码6.2 复杂性及稳定性分析
7 测试8 排序的稳定性8.1 概念8.2 意义8.3 排序算法的稳定性分析8.3.1 冒泡排序8.3.2 选择排序8.3.3 插入排序8.3.4 希尔排序8.3.5 归并排序8.3.6 快速排序
1 冒泡排序
1.1 代码
public class Bubble {
public static void sort(Comparable
[] a
) {
for(int i
=a
.length
-1;i
>0;i
--) {
for(int j
=0;j
<i
;j
++) {
if (greater(a
[j
],a
[j
+1])) {
exch(a
,j
,j
+1);
}
}
}
}
private static boolean greater(Comparable v
, Comparable w
) {
return v
.compareTo(w
) > 0;
}
private static void exch(Comparable
[] a
, int i
, int j
) {
Comparable t
= a
[i
];
a
[i
] = a
[j
];
a
[j
] = t
;
}
}
1.2 复杂性及稳定性分析
时间复杂度:O(n^2);空间复杂度:O(1);稳定性:稳定;
2 选择排序
2.1 代码
public class Selection {
public static void sort(Comparable
[] a
){
for(int i
=0;i
<a
.length
-1;i
++) {
int minIndex
= i
;
for(int j
=i
+1;j
< a
.length
;j
++) {
if(greater(a
[minIndex
],a
[j
])) {
minIndex
= j
;
}
}
exch(a
, i
, minIndex
);
}
}
private static boolean greater(Comparable v
, Comparable w
) {
return v
.compareTo(w
) > 0;
}
private static void exch(Comparable
[] a
, int i
, int j
) {
Comparable t
= a
[i
];
a
[i
] = a
[j
];
a
[j
] = t
;
}
}
2.2 复杂性及稳定性分析
时间复杂度:O(n^2);空间复杂度:O(1);稳定性:不稳定;
3 插入排序
3.1 代码
public class Insertion {
public static void sort(Comparable
[] a
) {
for(int i
=1;i
< a
.length
;i
++) {
for(int j
=i
;j
>=1;j
--) {
if (greater(a
[j
-1],a
[j
])) {
exch(a
, j
, j
-1);
}else {
break;
}
}
}
}
private static boolean greater(Comparable v
, Comparable w
) {
return v
.compareTo(w
) > 0;
}
private static void exch(Comparable
[] a
, int i
, int j
) {
Comparable t
= a
[i
];
a
[i
] = a
[j
];
a
[j
] = t
;
}
}
3.2 复杂性及稳定性分析
时间复杂度:O(n^2);空间复杂度:O(1);稳定性分析:稳定;
4 希尔排序
4.1 代码
public class Shell {
public static void sort(Comparable
[] a
) {
int N
= a
.length
;
int h
= 1;
while(h
<N
/2) {
h
= h
* 2 + 1;
}
while(h
>=1) {
for(int i
=h
;i
<N
;i
++) {
for(int j
=i
;j
>=h
;j
-=h
) {
if(greater(a
[j
-h
],a
[j
])) {
exch(a
, j
, j
-h
);
}else {
break;
}
}
}
h
/= 2;
}
}
private static boolean greater(Comparable v
, Comparable w
) {
return v
.compareTo(w
) > 0;
}
private static void exch(Comparable
[] a
, int i
, int j
) {
Comparable t
= a
[i
];
a
[i
] = a
[j
];
a
[j
] = t
;
}
}
4.2 复杂性及稳定性分析
时间复杂度:最好情况O(n),最坏情况O(n^2),平均O(n ^ 1.3);空间复杂度:O(1);稳定性:不稳定;经过测试,希尔排序性能远高于插入排序;
5 归并排序
5.1 代码
public class Merge {
private static Comparable
[] assist
;
public static void sort(Comparable
[] a
) {
assist
= new Comparable[a
.length
];
int lo
= 0;
int hi
= a
.length
-1;
sort(a
,lo
,hi
);
}
private static void sort(Comparable
[] a
,int lo
, int hi
) {
if (lo
==hi
) {
return;
}
int mid
= (lo
+hi
)/2;
sort(a
,lo
,mid
);
sort(a
,mid
+1,hi
);
merge(a
,lo
,mid
,hi
);
}
private static void merge(Comparable
[] a
, int lo
, int mid
, int hi
) {
int i
= lo
;
int p1
= lo
;
int p2
= mid
+1;
while(p1
<=mid
&& p2
<=hi
) {
if (greater(a
[p1
],a
[p2
])) {
assist
[i
++] = a
[p2
++];
} else {
assist
[i
++] = a
[p1
++];
}
}
while (p1
<=mid
) {
assist
[i
++] = a
[p1
++];
}
while (p2
<=hi
) {
assist
[i
++] = a
[p2
++];
}
for (int index
=lo
;index
<=hi
;index
++) {
a
[index
] = assist
[index
];
}
}
private static boolean greater(Comparable v
, Comparable w
) {
return v
.compareTo(w
) > 0;
}
}
5.2 复杂性及稳定性分析
时间复杂度:O(nlogn);空间复杂度:O(n);稳定性:稳定;与希尔排序在处理大批量数据时性能差别不大;
6 快速排序
6.1 代码
public class Quick {
public static void sort(Comparable
[] a
) {
int lo
= 0;
int hi
= a
.length
- 1;
quicksort(a
, lo
, hi
);
}
private static void quicksort(Comparable
[] a
, int lo
, int hi
) {
if (lo
>= hi
) return;
Comparable key
= a
[lo
];
int left
= lo
;
int right
= hi
;
while(left
< right
){
while(greaterOrequal(a
[right
],key
) && left
< right
){
right
--;
}
while (greaterOrequal(key
,a
[left
]) && left
< right
){
left
++;
}
exch(a
,left
,right
);
}
exch(a
, lo
, left
);
quicksort(a
, lo
, left
- 1);
quicksort(a
, left
+ 1, hi
);
}
private static boolean greaterOrequal(Comparable v
, Comparable w
) {
return v
.compareTo(w
) >= 0;
}
private static void exch(Comparable
[] a
, int i
, int j
) {
Comparable t
= a
[i
];
a
[i
] = a
[j
];
a
[j
] = t
;
}
}
6.2 复杂性及稳定性分析
时间复杂度:最好情况O(nlogn),最坏情况O(n^2),平均O(nlogn);空间复杂度:O(logn);稳定性:不稳定;
7 测试
public class Test {
public static void main(String
[] args
) throws Exception
{
Integer
[] arr
= {8,6,1,2,7,40,8,56,21,88};
Quick
.sort(arr
);
System
.out
.println(Arrays
.toString(arr
));
}
}
[1, 2, 6, 7, 8, 8, 21, 40, 56, 88]
8 排序的稳定性
8.1 概念
数组arr有若干元素,其中A等于B,并且A在B前,如果使用某种排序算法,能保证A依然在B前,那么该排序算法就是稳定的。
8.2 意义
如果一组数据只需要一次排序,稳定性没有意义;一组数据需要多次排序,稳定性有意义;例如对一组商品对象排序,第1次排按价格低到高,第二次按销量低到高。如果第二次排序稳定,那么相同销量的商品依然保持价格低到高的顺序展现,只有销量不同的对象才需要重新排序。如此既保持了第一次排序的意义,又减少了系统开销。
8.3 排序算法的稳定性分析
8.3.1 冒泡排序
只有当arr[i]>arr[i+1]的时候,才会交换元素位置,相等的时候不交换。
所以冒泡排序是稳定的。
8.3.2 选择排序
选择排序是给每个位置选择当前元素最小的。例如有数据{5(1),8,5(2),2,9},第一遍选择到的最小元素为2,所以5(1)会和2进行位置交换,此时5(1)到了5(2)的后面,破坏了稳定性。
所以选择排序是不稳定的。
8.3.3 插入排序
插入排序是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果不比它小则直接插入在其后面,否则一直往前找直到找到它插入的位置。
如果碰见一个和插入元素相等的,那么把要插入的元素放在相等元素的后面,相等元素的前后顺序没有改变。
所以插入排序是稳定的。
8.3.4 希尔排序
希尔排序是按照不同步长对元素进行插入排序,虽然一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱。
所以希尔排序是不稳定的。
8.3.5 归并排序
归并排序在归并过程中,只有当前面的元素比后面的元素大时才会交换位置,如果元素相等则先加入前面的元素,不会破坏稳定性。
所以归并排序是稳定的。
8.3.6 快速排序
快速排序需要一个基准值,在基准值右侧找一个比基准值小的元素,在基准值左侧找一个比基准值大的元素,然后交换这两个元素,会破坏稳定性。
所以快速排序是不稳定的。