Java基础排序算法

目录

插入排序

选择排序

快速排序

冒泡排序

希尔排序

归并排序

基数排序

堆排序


稳定的排序算法:排序后相同数值的元素位置不变。

插入排序

稳定的排序方法。

将一个数据插入到已经排好序的有序数组中,从而得到一个新的有序数组,算法适用于少量数据的排序。

public class InserSort extends Sort {
    //从小到大排列
    @Override
    public void sort(int[] array) {
       int length = array.length;
       //从数组的第二个位置开始向前比较
        for (int i = 1; i < length; i++) {
            int temp = array[i];//待插入元素
            int j = i-1;//已经排序好的数组最后一位
            while (j>=0&&array[j]>temp){
                //如果大于待插入元素,就将元素向后移动一位,此时位置j的元素待插入,继续比较
                array[j+1] = array[j];
                j--;
            }
            //跳出循环后,j的位置小于待插入元素
            array[j+1] = temp;//将待插入元素插入到j+1的位置中
        }
    }

}

选择排序

不稳定的排序方法。

从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。

public class SelectSort extends Sort {
    @Override
    public void sort(int[] array) {
        int length = array.length;
        for (int i = 0; i < length; i++) {
            int temp = array[i];
            int index = i;
            for (int j = i; j < length; j++) {
                if(temp>array[j]){
                    temp = array[j];
                    index = j;
                }
            }
            if(index!=i){
                swap(array,i,index);
            }
        }
    }

public void swap(int[] data, int i, int j){
        int tmp=data[i];
        data[i]=data[j];
        data[j]=tmp;
    }

}

快速排序

不稳定的算法

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序。

可以用数组第一个数作为基准进行比较

public class QuickSort extends Sort {

    @Override
    public void sort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }

    public void quickSort(int[] array, int start, int end) {
      int pivotNum = array[start];
      int low = start;
      int hight = end;
      while (low<hight){
          while (low<hight&&array[hight]>=pivotNum){
              hight--;
          }
          array[low] = array[hight];
          while (low<hight&&array[low]<=pivotNum){
              low++;
          }
          array[hight] = array[low];
      }
      array[low] = pivotNum;
      if(low+1<end)quickSort(array,low+1,end);
      if(low-1>start)quickSort(array,start,low-1);
    }
}

冒泡排序

稳定的排序算法

让数组当中相邻的两个数进行比较,数组当中比较小(或比较大)的数值向下沉;外层for循环控制循环次数,内层for循环控制相邻的两个元素进行比较。直到没有相邻元素需要交换,排序完成。

public class BubbleSort extends Sort {
    @Override
    public void sort(int[] array) {
        int length = array.length;
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length - 1 - i; j++) {
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                }
            }
        }
    }

public void swap(int[] data, int i, int j){
        int tmp=data[i];
        data[i]=data[j];
        data[j]=tmp;
    }

}

希尔排序

不稳定的排序算法

是插入排序的一种,又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。

把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,所有元素被分成一组,排序终止。

初始增量可以为数组长度的1/2,每次再取1/2。

public class ShellSort extends Sort {

    @Override
    public void sort(int[] array) {
        int length = array.length;
        int d = length/2;
        while (d>0){
            for (int i = 0; i < d; i++) {
                for (int j = i+d; j < length; j+=d) {
                    int num = array[j];
                    int k = j-d;
                    while (k>=0&&num < array[k]){
                        array[k+d] = array[k];
                        k-=d;
                    }
                    array[k+d] = num;
                }
            }
            d/=2;
        }
    }
}

归并排序

稳定的排序方法

将已有序的子序列合并,得到完全有序的序列。

    //归并排序:递归的将2个有序数组合并成一个。
    public int[] mergeSort(int[] array, int low, int hight) {
        //如果low == hight,则表示不能继续递归,直接返回元素
        if(low==hight){
            return new int[]{array[low]};
        }
        //找到中间下标
        int mid = low+(hight-low)/2;
        //对左右2边数组排序
        int[] leftArr = mergeSort(array, low, mid);
        int[] rightArr = mergeSort(array, mid + 1, hight);
        //将2个有序数组合并成新的有序数组
        int[] newArr = new int[leftArr.length+rightArr.length];
        int i = 0;int j = 0;int k = 0;
        while (i<leftArr.length&&j<rightArr.length){
            newArr[k++] = leftArr[i]<rightArr[j]?leftArr[i++]:rightArr[j++];
        }
        while (i<leftArr.length){
            newArr[k++] = leftArr[i++];
        }
        while (j<rightArr.length){
            newArr[k++] = rightArr[j++];
        }
        return newArr;
    }

基数排序

稳定的排序算法

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

先排好个位,然后排好各位的基础上排十位,以此类推,直到遍历最高位次,排序结束。

初始化10个桶(固定的),桶下标为0-9;

通过得到待排序数字的个、十、百等位的数字,把这个数字对应的元素放到对应的桶中;

基数排序有两种排序方式:LSD和MSD,最小位优先(从右边开始)和最大位优先(从左边开始);

LSD排序:

//d是数组元素的最大位数(几位数)
private void radixSort(int[] aar,int d){
        int m = 1;
        int n = 1;
        int k = 0;
        int length = aar.length;
        int[][] temp = new int[10][length];
        int[] orders = new int[10];
        while (m<=d){
            for (int i = 0; i < length; i++) {
                int lsd = (aar[i]/n)%10;
                temp[lsd][orders[lsd]] = aar[i];
                orders[lsd]++;
            }
            for (int i = 0; i < 10; i++) {
                if(orders[i]!=0){
                    for (int j = 0; j < orders[i]; j++) {
                        aar[k++] = temp[i][j];
                    }
                    orders[i] = 0;
                }
            }
            k = 0;
            n*=10;
            m++;
        }
    }

堆排序

不稳定的排序算法

了解二叉树的概念:https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91/1602879?fr=aladdin

堆:一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

在堆的数据结构中,堆中的最大值(大顶堆)或最小值(小顶堆)总是位于根节点。(取决于从小到大还是从大到小排序)

排序过程:将堆的末端子节点作调整,使得子节点永远大于或小于父节点;将根节点与最后一个节点交换,断开最后一个节点后,重新构建大顶推(或小顶推),递归排序。

public class HeapSort extends Sort {
    @Override
    public void sort(int[] array) {
        System.out.println("开始排序");
        int length= array.length;
        //循环建堆
        for(int i=0;i<length-1;i++){
            //建堆
            buildMaxHeap(array,length-1-i);
            //交换堆顶和最后一个元素
            swap(array,0,length-1-i);
            System.out.println(Arrays.toString(array));
        }
    }
    //对data数组从0到lastIndex建大顶堆,父节点:有叶子的节点,除根节点外也是叶子节点
    private void buildMaxHeap(int[] array, int lastIndex) {
        //从lastIndex处节点(最后一个节点)的父节点开始
        for(int i=(lastIndex-1)/2;i>=0;i--){
            //如果当前i节点的子节点存在
            while(i*2+1<=lastIndex){
                //i节点的左子节点的索引
                int biggerIndex=2*i+1;
                //如果biggerIndex小于lastIndex,即biggerIndex+1代表的i节点的右子节点存在
                if(biggerIndex<lastIndex){
                    //若果右子节点的值较大
                    if(array[biggerIndex]<array[biggerIndex+1]){
                        //biggerIndex总是记录较大子节点的索引
                        biggerIndex++;
                    }
                }
                //如果i节点的值小于其较大的子节点的值
                if(array[i]<array[biggerIndex]){
                    //交换他们
                    swap(array,i,biggerIndex);
                    //将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
                }else{
                    break;
                }
            }
        }
    }
    public void swap(int[] data, int i, int j){
        int tmp=data[i];
        data[i]=data[j];
        data[j]=tmp;
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值