【算法4】排序

1、选择、插入、冒泡

import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;
import java.util.Stack;

class Sort{
    public static int[] swap(int[]nums,int i, int j){
        int temp;
        temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
        return nums;
    }
    //选择排序
    public static void SelectS(int[] nums) {
        int minNum;
        for (int i = 0;i < nums.length; i++){
            minNum = i;
            for(int j = i+1;j < nums.length; j++){
                if( nums[minNum] > nums[j]){
                    minNum = j;
                }
            }
            swap(nums,i,minNum);
        }
        System.out.println( Arrays.toString(nums));
    }
    //冒泡排序
    public static void MaoPaoS(int[] nums){
        int maxNum,N;
        N = nums.length;
        boolean hasSort = true;  //在一轮循环中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。
        for(int i = N - 1; i > 0 && hasSort;i--){
            hasSort = false;
            for(int j = 0; j < nums.length-1 ;j++){
                if(nums[j] > nums[j+1]){
                    hasSort = true;
                    swap(nums,j,j+1);
                }
            }
        }
        System.out.println( Arrays.toString(nums)); //[1, 2, 3, 4, 5, 6]
    }

    //插入排序
    public static void InsertS(int[] nums){
        int N;
        N = nums.length;
        for (int i = 1;i < N; i++){  //与当前位置的前面所有位置的数进行比较,小于,则调换
            for(int j = i;j > 0 && (nums[j-1]> nums[j]); j--){
                swap(nums,j,j-1);
            }
        }
        System.out.println( Arrays.toString(nums));
    }

    //
}

2、归并

//自顶向下的归并排序
class Merge{
    /*
    * 分治的思想,将数组分为两个子数组,分别排序,再合并为一个
    * 时间复杂度:NlogN
    * */
    private static int[] aux;

    private static void merge(int[] nums,int lo, int mid, int hi){
        int i = lo, j = mid + 1;
        int[] auk = new int[ hi + 1 ];
        for( int k = lo; k <= hi; k++){  //copy
            auk[k] = nums[k];
        }
        for(int k = lo; k <= hi; k++){
            if( i > mid )   //左边用尽,取右边得元素
                nums[k] = auk[j++];
            else if( j > hi )   //右边用尽,取左边得元素
                nums[k] = auk[i++];
            else if(auk[i] < auk[j])  // 右半边得当前元素小于左半边得当前元素(取右半边的元素)
                nums[k] = auk[j++];
            else
                nums[k] = auk[i++];
        }

    }
    private static void mergeSort(int[] nums,int lo, int hi){
        if(hi <= lo)
            return;
        int mid = lo + (hi - lo)/2;
        mergeSort(nums, lo, mid); //将左边排序
        mergeSort(nums,mid+1,hi); //右边排序
        merge(nums, lo, mid, hi);  //归并
    }
    public static void mergeSort(int[] nums){
        mergeSort(nums, 0, nums.length-1);
        System.out.println( Arrays.toString(nums));   // [6, 5, 4, 3, 2, 1]
    }
}

 

3、快排

【主要思想】:将待排序数组以某一个元素为阈值分为两个子列,一个子列包含所有比改阈值小的元素,另一个子列反之。这样只要将这两个子列排好序,整个数组也就排好序了。这里有一个关键的子过程就是划分的过程Partition,一般可以选择数组中任意的元素作为划分阈值,这里选择的是数组中最右端的元素。

【Partition】:使用了二分查找类似的思想:使用两个索引器从数组的两端进行遍历,左边的索引器遇到比阈值大的元素停止,右边的索引器遇到比自己小的元素停止,然后交换这两个元素,依次循环。这样数组就划分为了比该阈值大和小(含等于)两个子列了。

//快排
class Quick{

    public static void qSort(int[] nums){
//        Collections.shuffle(nums);
        quickSort(nums, 0, nums.length-1);
        System.out.println( Arrays.toString(nums));  //[6, 5, 4, 3, 2, 1]
    }

    private static void quickSort(int[] nums, int lo, int hi) {
        if(hi < lo) return;
        int j = partition(nums, lo, hi); //切分
        quickSort(nums, lo, j-1);   //左排
        quickSort(nums, j+1, hi);   // 右排
    }
    // 找切分点
    private static int partition(int[] nums, int lo, int hi) {
        int i = lo,j = hi+1;
        int v = nums[lo];
        while(true) {
            while (nums[++i] > v) {
                if (i == hi) break;
            }
            while (nums[--j] < v) {
                if (j == lo) break;
            }
            if (i >= j) break;
            swap(nums, i, j);
        }
        swap(nums, lo, j);
        return j;
    }
    public static int[] swap(int[]nums,int i, int j){
        int temp;
        temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
        return nums;
    }
}

 

4、堆排序

思想:一个一个的插入,上浮,建最大堆;输出时,将第一个数与末尾的数交换位置,删除最后一个数(即最大值),第一个数再执行下沉的操作;再交换,再删除,输出整个排序序列;

    public static void swim(int k){
        /*
        * 上浮:和父节点比较,大于父节点,就交换,上浮
        * */
        while( k > 1 && (pq[k/2] < pq[k])){
            swap(pq,k/2, k);
            k = k/2;
        }
    }
    public static void sink(int k){
        /*
        * 下沉:某结点比它的两子节点中最大的还小,就交换,下沉
        * */
        int N = pq.length;
        while(2*k < N){
            int j = 2*k;
            if(j < N && (pq[j] < pq[j+1]))
                j += 1;
            if(!(pq[k] < pq[j]))
                break;
            swap(pq, k, j);
            k = j;
        }
    }

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值