java 排序算法

冒泡排序

对一个含有N个元素的数组,进行排序时,最少需要一次循环,最多需要经过N-1次循环;

需要两个for循环和一个判断条件;

第一轮结束,就可以在末尾得到最小或最大值;

public void maoPao(){
    int[] arr=new int[5,78,9,20,7,1,60];

    for(int len = arr.length-1; i>0; i--){//每轮遍历次数比上一次要少1
                
        for(int j=0;j<len;j++){
            //如果前一个数大于下一个数,就交换
            if(arr[j] > arr[j+1]){//如果是降序,就把 > 改为 <
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    } 
}


//优化:若数组就是有序排列的,则最少只需一次循环;
public void maoPao1(){
    int[] arr=new int[5,7,9,20,78,99];

    for(int len = arr.length-1; i>0; i--){//每轮遍历次数比上一次要少1   
       
        //判断是否进行过交换操作;
        boolean sorted = true;

        for(int j=0;j<len;j++){
            //如果前一个数大于下一个数,就交换
            if(arr[j] > arr[j+1]){//如果是降序,就把 > 改为 <
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
                sorted = false;
            }
        }

         //当某一次遍历完,发现一次交换操作都没有,则表示数组就是有序排列的;则就结束;
        if(sorted){
           break;//结束循环;
        }
        
    } 
}


选择排序

核心原理:不断从数组中找出最大值,然后把最大值放入末尾;

需要两个for循环、一个判断条件、一个index;

public void xuanZe(){
    int[] arr=new int[5,78,9,20,7,1,60];

    for(int i = arr.length-1; i>0; i--){//每轮遍历次数比上一次要少1
         
        int maxIndex=0;
        for(int j=0;j<i;j++){
            //如果前一个数大于下一个数,就记录最大值的下标
            if(arr[maxIndex] < arr[j+1]){
                maxIndex = j+1;
            }
        }

        int max = arr[maxIndex];
        arr[maxIndex] = arr[i];
        arr[i] = max;
    } 
}

插入排序

原理:从数组中获取一个数,并和其他数比较,选择合适的位置插入;

需要2个循环、一个判断条件、一个要对比的元素cur;

public void chaRu(){
    int[] arr=new int[5,78,9,20,7,1,60];

    for(int i = 0; i< arr.length-1; i++){
         
        int pre = i;
        int cur = arr[pre+1];
        while(pre >=0 && cur <arr[pre]){
            arr[pre+1]=arr[pre];
            pre--; 
        }
        arr[pre+1]=cur;

    } 
}

希尔排序

原理:每次将数组按步长step分为N行的矩阵;每列进行插入排序;直到步长为1;

需要3个循环: 一个步长循环,一个插入排序算法;

原数组 [2,6,19,28,3,7,10,22,18]
步长数组:长度/2 ;  steps=[4,2,1];
第1次步长4:
[2, 6, 19, 28]
[3, 7, 10, 22]
[18]

每列进行插入排序:
[2, 6, 10, 22]
[3, 7, 19, 28]
[18]
结果:
[2, 6, 10, 22, 3, 7, 19, 28,18]

第2次步长2:
[2,   6]
[10, 22]
[3,   7]
[19, 28]
[18]

每列进行插入排序:
[2,   6]
[3,   7]
[10, 22]
[18, 28]
[19]
结果:
[2, 6, 3, 7, 10, 22, 18, 28,19]

第3次步长1:
[2]
[6]
[3]
[7]
[10]
[22]
[18]
[28]
[19]
每列进行插入排序:
[2]
[3]
[6]
[7]
[10]
[18]
[19]
[22]
[28]
结果:
[2, 3, 6, 7, 10, 18, 19, 22,28]
private int[] array = {12,20,30,3,6,22,55,100};

//获取步长数组
private List<Integer> shellSequence(){
    List<Integer> sequence = new ArrayList<>();
    int step = array.length;
    while ((step = step>>1) > 0){
       sequence.add(step);
    }
    return sequence;
}

public void paixu(){

     List<Integer> sequence = shellSequence();
     for(Integer step: sequence){
            shellByStep(step);
     }
}

private void shellByStep(int step) {
    int cur = 0;
    int j = 0;
    // 第一次 step =4
    for(int i= step;i<array.length;i++){
       cur = array[i]; // 这里的cur = 6;
       for(j=i-step;j>=0;j-=step){
          int a = array[j];
          if(cur < a){ //  如果拿出来对比的数据 比已经存在的某个数据小
             array[j+step] = array[j];
          }else{  //直接跳出循环
              break;
          }
       }

       array[j+step] = cur;
    }
}

计数排序

原理:找出数组a中最大的值n,生成一个新的长度为n的数组b,旧数组a的元素作为新数组b的下标,往里面填元素个数;

优点:性能比冒泡、插入、选择都快;

缺点:空间占用大,需要生成一个新的数组,且长度可能无限大;

  public int[] countSort(int[] arr){
        int max = Integer.MIN_VALUE;//  最小
        int min = Integer.MAX_VALUE;

        //找出数组中的最大最小值
        for(int i = 0; i < arr.length; i++){
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }

        int help[] = new int[max];

        //找出每个数字出现的次数
        for(int i = 0; i < arr.length; i++){
            // 做偏移
            int mapPos = arr[i] - min;
            help[mapPos]++;
        }

        //还原数据
        int index = 0;
        for(int i = 0; i < help.length; i++){
            while(help[i]-- > 0){
                arr[index++] = i+min;
            }
        }

        return arr;
    }


归并排序

和希尔排序相反,分组从2开始,2、4、8..;

    // 归并排序
    public void mergeSort(int[] nums) {
        int[] tmpArray = new int[nums.length];
        mSort(nums, tmpArray, 0, nums.length - 1);
    }

    public void mSort(int[] nums, int[] tmps, int left, int right) {
        int center;
        if (left < right) {
            center = (left + right) / 2;
            mSort(nums, tmps, left, center);
            mSort(nums, tmps, center + 1, right);
            merge(nums, tmps, left, center + 1, right);
        }
    }

    // 空间归并
    public void merge(int[] nums, int[] tmps, int lpos, int rpos, int rightEnd) {
        int i, leftEnd, numElements, tmpPos;
        leftEnd = rpos - 1;
        tmpPos = lpos;
        numElements = rightEnd - lpos + 1;
        while (lpos <= leftEnd && rpos <= rightEnd) {
            if (nums[lpos] <= nums[rpos])
                tmps[tmpPos++] = nums[lpos++];
            else
                tmps[tmpPos++] = nums[rpos++];
        }
        while (lpos <= leftEnd)
            tmps[tmpPos++] = nums[lpos++];
        while (rpos <= rightEnd)
            tmps[tmpPos++] = nums[rpos++];
        for (i = 0; i < numElements; i++, rightEnd--)
            nums[rightEnd] = tmps[rightEnd];
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值