java实现排序算法

一、堆排序

import java.util.*;

public class Main {
    public static void main(String[] args) {
        int[] arr = {27,15,19,18,28,34,65,49,25,37};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void createBigHeap(int[] arr) {
        for (int i = (arr.length-1-1)/2; i >= 0 ; i--) {
            adjustDown(arr,i,arr.length);
        }
    }

    public static void adjustDown(int[] arr,int parent,int len) {
        int child = 2 * parent + 1;
        if (child + 1 < len && arr[child] < arr[child + 1]) {
            child++;
        }
        while (child < len) {
            if (arr[child] > arr[parent]) {
                int tmp = arr[child];
                arr[child] = arr[parent];
                arr[parent] = tmp;
                parent = child;
                child = 2 * parent + 1;
            } else {
                break;
            }
        }
    }
    //时间复杂度(不管最好还是最坏):O(n * log2(n))
    //空间复杂度:O(1)
    public static void heapSort(int[] arr) {
        createBigHeap(arr);
        int end = arr.length - 1;
        while (end > 0) {
            int tmp = arr[0];
            arr[0] = arr[end];
            arr[end] = tmp;
            adjustDown(arr,0,end);
            end--;
        }
    }
}

二、插入排序

1.直接插入排序

     /**
     * 时间复杂度:最坏情况下:o(n^2)
     *          最好情况下:o(n)
     *          结论:越有序越快
     *                (1)会用在大部分有序的情况下 (2)也会用在一些排序的优化上(快速排序)
     * 空间复杂度:o(1)
     * 稳定性:稳定的排序
     * @param arr
     */
    public static void insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i - 1;
            for (; j >= 0 ; j--) {
                if (tmp < arr[j]) {
                    arr[j+1] = arr[j];
                } else {
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }

2.希尔排序

     /**
     * 希尔
     * 时间复杂度:最好:o(n)  最坏:o(n^2)
     * 空间复杂度:o(1)
     * 稳定性:不稳定
     * @param arr
     */
    public static void shellSort(int[] arr) {
        int gap = arr.length;
        while (gap > 1) {
            shell(arr,gap);
            gap = gap / 2;
        }
        shell(arr,1);
    }
    public static void shell(int[] arr,int gap) {
        for (int i = gap; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i-gap;
            for (; j >= 0; j-=gap) {
                if (tmp < arr[j]) {
                    arr[j+gap] = arr[j];
                } else {
                    break;
                }
            }
            arr[j+gap] = tmp;
        }
    }

三、选择排序

1.直接选择排序


     /**
     * 时间复杂度:O(n^2)
     * 空间复杂度:O(1)
     * 稳定性:不稳定
     * @param arr
     */
    public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = i+1; j < arr.length; j++) {
                if (arr[i] > arr[j]) {
                    int tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }

2.双向选择排序(了解)

四、冒泡排序

public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length-1; i++) {
            boolean isSorted = true;//判断数列是否有序
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j+1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                    isSorted = false;
                }
            }
            if (isSorted) {
                break;
            }
        }
    }

五、快速排序(重要)

     /**
     
     分治思想:什么时候效率最高,可以把待排序序列均匀的划分
     * 时间复杂度:最好情况:O(nlog2(n))  最坏情况(有序序列):O(n^2)
     * 空间复杂度: 最好情况:O(log2(n))   最坏情况:O(n)
     * 稳定性:不稳定
     * @param arr
     */
    public static void quickSort(int[] arr) {
        quick(arr,0,arr.length-1);
    }
    public static void quick(int[] arr,int low,int end) {
        if (low < end) {
            int pivot = pivot(arr,low,end);
            quick(arr,low,pivot-1);
            quick(arr,pivot+1,end);
        }
    }
    public static int pivot(int[] arr,int start,int end) {
        int tmp = arr[start];
        while (start < end) {
            while (arr[end] >= tmp && end > start) {
                end--;
            }
            arr[start] = arr[end];
            while (tmp >= arr[start] && start < end) {
                start++;
            }
            arr[end] = arr[start];
        }
        arr[start] = tmp;//start == end
        return start;
    }

非递归:

public static void quickSort(int[] arr) {
        Stack<Integer> stack = new Stack<>();
        int low = 0;
        int high = arr.length-1;
        int piv = pivot(arr,low,high);
        if (piv > low+1) {//左侧超过两个数据
            stack.push(low);
            stack.push(piv-1);
        }
        if (piv < high-1) {//右侧超过两个数据
            stack.push(piv+1);
            stack.push(high);
        }
        while (!stack.empty()) {
            high = stack.pop();
            low = stack.pop();
            piv = pivot(arr,low,high);
            if (piv > low+1) {
                stack.push(low);
                stack.push(piv-1);
            }
            if (piv < high-1) {
                stack.push(piv+1);
                stack.push(high);
            }
        }
    }

优化算法:三数取中法

    public static void medianOfThree(int[] arr,int low,int high) {
        int mid = (low + high) / 2;
        if (arr[mid] > arr[low]) {
            swap(arr,low,mid);
        }
        if (arr[mid] > arr[high]) {
            swap(arr,mid,high);
        }
        if (arr[low] > arr[high]) {
            swap(arr,low,high);
        }
    }
    public static void quick(int[] arr,int low,int end) {
        if (low < end) {
            medianOfThree(arr,low,end);
            int pivot = pivot(arr,low,end);
            quick(arr,low,pivot-1);
            quick(arr,pivot+1,end);
        }
    }

六、归并排序(重要)

/**
     * 时间复杂度:O(n*log2(n))
     * 空间复杂度:O(n)
     * @param arr
     */
    public static void mergeSort(int[] arr) {
        mergeSortInternal(arr,0,arr.length-1);
    }
    public static void mergeSortInternal(int[] arr,int low,int high) {
        if (low >= high) return;
        int mid = (low + high) / 2;
        mergeSortInternal(arr,low,mid);
        mergeSortInternal(arr,mid+1,high);
        merge(arr,low,mid,high);
    }
    public static void merge(int[] arr,int low,int mid,int high) {
        int s1 = low;
        int s2 = mid+1;
        int[] tmp = new int[high-low+1];
        int k = 0;//tmp的下标
        while (s1 <= mid && s2 <= high) {
            if (arr[s1] <= arr[s2]) {
                tmp[k++] = arr[s1++];
            } else {
                tmp[k++] = arr[s2++];
            }
        }
        //结束循环后可能s1还有值
        while (s1 <= mid) {
            tmp[k++] = arr[s1++];
        }
        //结束循环后可能s2还有值
        while (s2 <= high) {
            tmp[k++] = arr[s2++];
        }
        for (int i = 0; i < tmp.length; i++) {
            arr[i+low] = tmp[i];
        }
    }

海量数据排序问题
外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序

  1. 先把文件切分成 200 份,每个 512 M
  2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
  3. 进行 200 路归并,同时对 200 份有序文件做归并过程,最终结果就有序了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值