数据结构之排序(1)

排序的概念(Sort)

排序的分类

排序可基于数组进行排列,也可基于比较排列(依据数据的大小进行排序),也有原地排序,排序是运用非常广泛的基础算法,也是典型的多态算法。
排序共有七大排序方法,分别为:

  • 插入排序
  • 希尔排序(插入排序优化版)

基于选择排序的有:

  • 选择排序
  • 堆排序

此外还有:

  • 冒泡排序
  • 快速排序
  • 归并排序

今天会涉及到插入,冒泡,选择,堆排序
现在开始吧!!!

插入排序

代码实现

基本思想:
将要排序的部分分为【有序区间,无序区间】
每次执行的操作是:

  • 1.抓无序区间的第一张牌
  • 2.依次和有序区间的牌比较
  • 3.选择合适的位置插入
package sort;

public class Sort{
   public static void inserSort(long[] array){
   //数组一共有array.length个
   //故,子操作需执行array.length或array.length-1次
   for(int i = 0;i < array.length-1;i++){
   //有序区间【0,i+1)
   //因i已经等于0,所以i已有序,故为i+1
   //无序区间【i+1,array.length】
   //所以抓取出来的数是i+1
   long key = array[i+1];
   int j;
   //按倒序的顺序依次在有序区间进行比较[i,0]
   for(int j = 1,j >= 0,j--){//j就是要与key进行比较,有三种情况:
   //1.key<array[j] 把array[j]往后移,继续向前比较,key=array[j]
   //2.key==array[j] 不移把key放入array[j]后,array[j+1]=key,不需要继续比较
   //3.key>array[j] 把key放入array[j]后,array[j+1]=key,不需要继续比较
   if(key < array[j]){
      array[j+1] = array[j];
   }else{
      break;
     }
    array[j+1] = key;
   }
  }
}
   
   
测试代码

测试的四种情况:

  • 1.随机生成的乱序数
  • 2.已经有序
  • 3.已经无序
  • 4.完全相等
  • 扩展:测试不同规模的数据(10/1000/100w/10亿等)
//测试
//构建随机生成的乱序数
public static long[] BuildRandomArray(){
  Random random = new Random(20201018);
  long[] array = new long[10];
  for(int i = 0;i < 20; i++){
     array[i] = random.nextInt(100);
    }
    return array;
   }
 }

//构建完全有序数组
 public static long[] BuildOrderedArray(){
  long[] array = BuildRandomArray();
  Array.sort(array);
  return array;
 }

//构建完全逆序数组
 public static long[] BuildReverseArray(){
  long[] array = BuildOrderedArray();
  swap(array,0,9);
  swap(array,1,8);
  swap(array,2,7);
  swap(array,3,6);
  swap(array,4,5);
  return array;
}

//构建完全相等的数组
 public static long[] BuildEqualArray(){
   long[] array = new long[10];
   for(int i = 0;i < 10;i++){
      array[i] = 9;
    }
    return array;
 }

//swap
 public static void swap(long[] array,int i,int j){
   long t = array[i];
   array[i] = array[j];
   array[j] = t;
 } 

//主调用函数
 public static void main(string[] args){
  long[] a1 = BuildRandomArray();
 System.out.println(Arrays.toString(a1));
  inserSort(a1);
  System.out.println(Arrays.toString(a1));
}
时间复杂度

最好情况:O(n)有序排列数组
最坏情况:O(n^2)逆序排列数组
平均情况:O(n^2)

空间复杂度

最好/最坏/平均情况:O(1)
具有稳定性

冒泡排序

将区间中的1个大数依次排序到相应位置的过程称为冒泡过程。10个数需要9或10次冒泡过程。
基本思想与插入排序相同,都是将要排序的区间分为【无序区间,有序区间】

public static void bubbleSort(long[] array){
    //需要array.length-1次冒泡过程
    for(int i = 0;i < array.length-1;i++){
         //无序【0,array.length-i)
         //有序【array.length-i,array.length)
         //当循环1次时,数组中有1个有序数,所以循环i次,有序数字有i个

        //每次冒泡前,假设数组已经有序
        boolean inSorted = true;
        //进行冒泡排序
        for(int j = 0;j < array.length-i-1;j++){
        if(array[j] > array[j+1]){
           swap(array,j,j++);
           inSorted = false;
         }
       }
       if(inSorted){
          break;
        }
       }
      }
  } 
时间复杂度:
  • 最好情况:O(n) 有序数组(只走了一次内侧循环)
  • 最坏情况:O(n^2) 逆序
  • 平均情况:O(n^2)
空间复杂度:
  • 最好/最坏/平均:O(1)
    具有稳定性

选择排序

在这里插入图片描述基本思想:
通过遍历完全乱序区间选出其最大或最小的数,将其放入有序区间,依次循环。

如何在无序区间进行选择:

  • 1.遍历,找出最大数
  • 2.和无序区间的最后一个数进行比较
public static void selectSort(long[] array){
    for(int i =0; i < array.length-1;i++){
     //有序区间:【array.length-i,array.length)
     //无序区间:【0,array.length-i)
     int maxIndex = 0;//假设最大数是array[0]
     for(int j = 1;j < array.length-i;j++){
     if(array[j] > array[maxIndex]){
        maxIndex = j;
       }
      }
      //期望maxIndex指向无序区间的最大的数的下标
       swap(array,maxIndex,array.length-i-1);
}
时间复杂度:

最好/最坏/平均情况:O(n^2)

空间复杂度:

最好/最坏/平均情况:O(1)
不具备稳定性

堆排序

举个例子,已知一个数组【19,45,15,59,28,25,28,47,99,30】,建堆后为【99,59,28,47,30,25,15,19,45,28】如下图所示:
在这里插入图片描述对其中数字找最大数交换得【28,59,28,47,30,25,15,19,45,99】从堆中挑出最大的数放入有序区间,对下标0的数根据其大小进行向下调整,但不包括有序区间
在这里插入图片描述可得:
在这里插入图片描述接着依次循环完成排序。

代码实现
public static void heapSort(long[] array){
    //1.建大堆
   createHeap(array,array.length);
   //2.进行选择的过程,一共需要array.length-1组
   for(int i = 0;i <array.length-1;i++){
   //无序:【0,array.length-i】
   swap(array,0,array.length-i-1);
   //无序:【0,array.length-i-1】
   adjustDown(array,array.length-i-1,0);
   }
 }
 private static void adjustDown(long[] array,int size,int index){
 while(2*index + 1 < size){
   int maxindex = 2*index + 1;
   if(maxIndex + 1 < size && array[maxIndex + 1] > array[maxIndex]{
     maxIndex++;
   }
   if(array[index] >= array[maxIndex]){
     break;
   }
   swap(array,index,maxIndex);
   index = maxIndex;
    }
  }
  private static void createHeap(long[] array,int size){
  for(int i = (size-2) / 2;i >= 0;i--){
     adjustDown(array,size,i);
     }
    }
时间复杂度

最好/最坏/平均情况:O(n*log(n))

空间复杂度

最好/最坏/平均:O(1)
不具备稳定性

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值