Java实现八大排序算法(冒泡、选择、快速、归并、堆、插入、基数、希尔)

最近找工作,手撸一些基础的算法。写个博客顺便复习一下。

ps:有的算法不详细的讲步骤,不懂的算法请移步其他博客。

1、冒泡排序

/*
    冒泡排序 稳定 时O(n2) 空O(1)
     */
    public static void bubbleSort(int arr[]){
        //第一层循环确定遍历次数,每一层都可以将最大的一个数交换到数组最末尾
        for (int i = 1; i < arr.length; i++) {
            //声明一个布尔变量,数组有序的情况下结束排序,优化时间
            boolean n = false;
            for (int j = 0; j < arr.length - i; j++) {
                if(arr[j] >= arr[j + 1]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                    n = true;
                }
            }
            if(!n) break;
        }
    }

2、选择排序

 /*
    选择排序 不稳定 时O(n2) 空O(1)
     */
    public static void selectSort(int[] arr,int p){
        //设置p为递归的标记位从0开始,min为初始值,遍历一次数组找出最小值,下标用q记录
        if(p == arr.length-1) return;
        int min = arr[p];
        int q = -1;
        for (int i = p+1; i < arr.length; i++) {
            if(arr[i] < min){
                min = arr[i];
                q = i;
            }
        }
        //若找出最小值,将其交换至递归标志位
        if(q != -1){
            int temp = arr[p];
            arr[p] = arr[q];
            arr[q] = temp;
        }
        selectSort(arr,p+1);
    }

3、快速排序

   /*
        快速排序 不稳定 时O(n2)/O(nlogn) 空O(nlogn)
         */
    public static void QuickSort(int arr[],int left,int right){
        //设置每次递归的数组第一个数为标志位,设置两个指针分别指向除了标志位的最左和最右
        //循环:先从最右边往左找到比标志位小的,再从最左往右找比标志位大的,找到之后交换,直到两个指针碰在一起,循环结束。
        //最后将标志位与指针碰撞的位置交换
        //递归标志位两边的数组
        if(left>=right) return;
        int i = left;
        int j = right;
        int k = arr[left];
        while(i=k){
                j--;
            }
            while(i

4、归并排序

    /*
        归并排序 稳定 时O(nlogn) 空O(n) 二分+归并 logn+n
         */
    public static void Merge(int[] arr){
        Sort(arr,0,arr.length-1);
    }
    private static void Sort(int[] arr, int left, int right) {
        if(right - left < 1) return;
        int mid = (right + left)/2;
        //先将数组切分成最小的单元素
        Sort(arr,left,mid);
        Sort(arr,mid+1,right);
        merge(arr,left,mid,right);
    }
    private static void merge(int[] arr, int left, int mid, int right) {
        //将两个部分数组合在一起
        int[] Arr = new int[right-left+1];
        int l = left;
        int r = mid + 1;
        int i = 0;
        //先依据大小进行合并到临时数组直到其中一个部分数组合并完成
        while(l<=mid && r<=right){
            if(arr[l] <= arr[r]){
                Arr[i] = arr[l];
                i++;
                l++;
            }else {
                Arr[i] = arr[r];
                i++;
                r++;
            }
        }
        //再将另一个数组放进临时数组里
        if(l>mid){
            while(r<=right){
                Arr[i] = arr[r];
                i++;
                r++;
            }
        }else {
            while (l<=mid){
                Arr[i] = arr[l];
                i++;
                l++;
            }
        }
        i = 0;
        //最后将临时数组覆盖到原数组
        for (int j = left; j <=right ; j++) {
            arr[j] = Arr[i];
            i++;
        }
    }

5、堆排序

   /*
        堆排序 不稳定 时O(nlogn) 空O(1)
         */
    public static void heapSort(int[] arr){
        int i = arr.length;
        while(i>=2){
            //先找出最后一个非叶节点p
            int p = i/2;
            //p向前遍历,从右孩子往左孩子遍历
            //注意:每一次遍历结束后 i-- 这样就不用遍历排序好的节点了
            for(;p>0;p--){
                int l = 2*p;
                int r = 2*p+1;
                if(r<=i && arr[r-1]>arr[p-1]){
                    int temp = arr[p-1];
                    arr[p-1] = arr[r-1];
                    arr[r-1] = temp;
                }
                if(l<=i && arr[l-1]>arr[p-1]){
                    int temp = arr[p-1];
                    arr[p-1] = arr[l-1];
                    arr[l-1] = temp;
                }
            }
            int temp = arr[i-1];
            arr[i-1] = arr[0];
            arr[0] = temp;
            i--;
        }
    }

6、插入排序

  /*
        插入排序 稳定 时O(n2) 空O(1)
     */
    public static void insertSort(int[] arr){
        for (int i = 1; i < arr.length; i++) {
            //每次循环找出未排序的第一个数在已排序数组中的位置p
            int p = -1;
            for (int j = 0; j < i; j++) {
                if(arr[i] <= arr[j]){
                    p = j;
                    break;
                }
            }
            if(p != -1){
                int temp = arr[i];
                //将p位置往后的已排序数组后移一位,再将该数放入p位置
                for (int j = i-1; j >=p; j--) {
                    arr[j+1] = arr[j];
                }
                arr[p] = temp;
            }
        }
    }

7、基数排序

  /*
        基数排序 稳定 时O(logRB) 空O(n) R:基数 B:真数0-9
    */
    public static void radixSort(int[] arr){
        //求基数R
        int R = -1;
        for (int i = 0; i < arr.length; i++) {
            int count = 0;
            int num = arr[i];
            while(num !=0){
                num = num/10;
                count++;
            }
            R = R>count?R:count;
        }
        //声明一个队列(“桶”)为元素的,容量为10链,用于存储每次循环得到的中间数
        List> l = new LinkedList<>();
        for (int i = 0; i < 10; i++) {
            Queue q = new LinkedList<>();
            l.add(q);
        }
        for (int i = 0; i < R; i++) {
            for (int j = 0; j < arr.length; j++) {
                int r = getFigure(arr[j],i);
                l.get(r).offer(arr[j]);
            }
            int p = 0;
            //将链中的元素依次取出,进行下一次循环
            for (int j = 0; j < arr.length; j++) {
                while(!(l.get(j).isEmpty())){
                    arr[p] = l.get(j).poll();
                    p++;
                }
            }
        }
    }
    //获取i第k位的数
    public static int getFigure(int i,int k)
    {
        int[] a = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
        return (i/a[k])%10;
    }

8、希尔排序

这是我见过最简洁的希尔排序,也很容易懂。

该部分转自:https://blog.csdn.net/qq_33054265/article/details/82747330

  /*
        shell排序 稳定 时O() 空O(1)
    */
    public static void shellSort(int[] a) {
        int N = a.length;
        //希尔增量h
        for(int h = N / 2; h > 0; h /= 2){
            for(int i = h; i < N; i++){
                for(int j = i; j >= h && a[j] < a[j - h]; j -= h){
                    int temp = a[j];
                    a[j] = a[j-h];
                    a[j-h] = temp;
                }
            }
        }
    }

 

你可能感兴趣的:(Java,排序算法,Java)