一.基本概念
1.概念:
- 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。平时的上下文中,如果提到排序,通常指的是排升序(非降序)
2.稳定性
- 两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算
法。 - 下面用一个简单图给大家说明一下:图中给的数据有俩个3,如果排序之后,黑3还在红3之后,那么这样的排序就是稳定的,否则就是不稳定的。
3.Java常见排序
二.具体排序代码实现
1.直接插入排序
-
稳定性(稳定):稳定性排序在排序过程是不会发生跳跃性的交换数据
1.一个稳定的排序可以变成不稳定的排序;
2.一个本身就不稳定的是不可能变成稳定的; -
空间复杂度:O(1);
-
时间复杂度:
- 最好情况:O(n)数组有序的时候;
- 最坏情况:最坏情况O(n2)数组无序的时候;
-
思路:以升序为例
1.首先用i从头开始遍历数组;
2.接着在外面拿一个空间tmp,每一次都把arr[i]放进去;
3.然后定义一个变量j,j的初始值为i-1;
4.比较arr[j]和tmp大小,如果大于tmp,就在j+1位置放入arr[j];
5.一直直到i遍历完数组,也就排好了。
public static void insertsort(int[] arr){
for(int i = 1;i < arr.length;i++) {
int tmp = arr[i];
int j = i-1;
for (;j >= 0;j--){
if (arr[j] > tmp) {
arr[j+1] = arr[j];
}else{
break;
}
}
arr[j+1] = tmp;
}
}
2.希尔排序
- 稳定性(不稳定)
1.一个稳定的排序可以变成不稳定的排序;
2.一个本身就不稳定的是不可能变成稳定的;
-
空间复杂度:O(n^1.3) - O(n^1.5) ;
-
时间复杂度:
- 最好情况:O(n)数组有序的时候;
- 最坏情况:最坏情况O(n^2)数组无序的时候;
-
思路:升序为例
1.希尔排序实际上是对直接插入排序的优化;
2.对一组数据进行分组,比如下图分为5组,gap == 5,从0号位置开始,加gap,从而确定一组里面的元素,下面同种颜色就是一组;
3.然后每一组都用直接插入排序的方法,进行排序;
4.这一次排完,下一次在分为3组,在调用直接插入排序,下一次可以在分2组,也可以直接分一组;
5.一直分组到分为一组排完序,那么就排好序了;
6.那么大家肯定想知道gap怎么选择,大家有没有发现组数都说素数,所以组数根据数据大小,选择适当的素数组,例如下面这组数据有15个元素,就分别分为5,3,1组。
//希尔排序(优化直接插入排序)
public static void shellsort(int[] arr){
//1.首先获取组数gqp
int[] drr = {
5,3,1};//定义一个增量数组
for (int i = 0;i < drr.length;i++){
shell(arr,drr[i]);
}
}
//直接插入排序
public static void shell(int[] arr,int gap) {
for(int i = gap;i < arr.length;i++) {
int tmp = arr[i];
int j = i-gap;
for (;j >= 0;j -= gap){
if (arr[j] > tmp) {
arr[j+gap] = arr[j];
}else{
break;
}
}
arr[j+gap] = tmp;
}
}
3.结果测试
public class TestSort {
//直接插入排序
public static void insertsort(int[] arr){
for(int i = 1;i < arr.length;i++) {
int tmp = arr[i];
int j = i-1;
for (;j >= 0;j--){
if (arr[j] > tmp) {
arr[j+1] = arr[j];
}else{
break;
}
}
arr[j+1] = tmp;
}
}
//希尔排序(优化直接插入排序)将数组进行分组
public static void shellsort(int[] arr){
//1.首先获取组数gqp
int[] drr = {
5,3,1};//定义一个增量数组
for (int i = 0;i < drr.length;i++){
shell(arr,drr[i]);
}
}
//直接插入排序
public static void shell(int[] arr,int gap) {
for(int i = gap;i < arr.length;i++) {
int tmp = arr[i];
int j = i-gap;
for (;j >= 0;j -= gap){
if (arr[j] > tmp) {
arr[j+gap] = arr[j];
}else{
break;
}
}
arr[j+gap] = tmp;
}
}
//测试main方法
public static void main(String[] args) {
//直接插入排序
int[] arr = {
2,3,5,1,6,4};
insertsort(arr);
System.out.print("直接插入排序结果: ");
for (int i = 0;i < arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
//希尔排序
int[] arr1 = {
7,4,9,34,0,8,5,22,55,6,12,33,56,89,77};
shellsort(arr1);
System.out.print("希尔排序结果: ");
for (int i = 0;i < arr1.length;i++){
System.out.print(arr1[i]+" ");
}
System.out.println();
}
}