文章目录

  • Java——排序算法
  • 一、概览
  • 二、复杂度
  • 三、冒泡排序N2
  • 四、选择排序N2
  • 五、插入排序N2
  • 六、希尔排序nlogn
  • 七、堆排序nlogn
  • 八、归并排序nlogn
  • 九、快速排序


Java——排序算法

一、概览

Java中层级排序 java底层排序算法_i++

二、复杂度

Java中层级排序 java底层排序算法_Java中层级排序_02

三、冒泡排序N2

 两层循环,N2复杂度,外层i从头到尾,当i=1时,内层从头到尾-i,如果j大于j+1,交换j与j+1的元素,依次将最大的向后扔。

class MaoPao{
	public static void sort(int []arr){
		for(int i = 0;i<arr.length-1;i++){
			for(int j = 0;j<arr.length-1-i;j++){
				if (array[j + 1] < array[j]) {
                     int temp = array[j + 1];
                     array[j + 1] = array[j];
                     array[j] = temp;
                 }
			}
		}
	}
}

改进冒泡:加boolean标志位,如果在某轮循环中内部没发生交换,即代表已经排序完成了

/**
 * 终极版冒泡排序
 * 加入一个布尔变量,如果内循环没有交换值,说明已经排序完成,提前终止
 * @param arr
 */
public static void sortPlus(int[] arr){
        for(int i = 0; i < arr.length - 1; i++){
            // 初始化一个布尔值
            boolean flag = true;
            for(int j = 0; j < arr.length - i - 1 ; j++){
                if(arr[j] > arr[j+1]){
                    // 调换
                    int temp;
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                    // 改变flag
                    flag = false;
                }
            }
            if(flag){
                break;
            }
        }
}

四、选择排序N2

 首先在未排序数列中找到最小元素,然后将其与数列的首部元素进行交换,然后,在剩余未排序元素中继续找出最小元素,将其与已排序数列的末尾位置元素交换。

public static void sort(int[] arr){
    for(int i = 0; i < arr.length - 1 ; i++){
        int min = i; 
        for (int j = i + 1; j < arr.length ;j++){
             if(arr[j] < arr[min]){
                 // 找到当前遍历区间最小的值的索引
                 min = j;
             }
        }
        if(min != i){
            // 发生了调换
            int temp =  arr[min];
            arr[min] = arr[i];
            arr[i] = temp;
        }
    }
}

五、插入排序N2

Java中层级排序 java底层排序算法_java_03

public class InsertSort {
    public static void sort(int[] arr) {
            for (int i = 1; i < arr.length; i++) {
                //挖出一个要用来插入的值,同时位置上留下一个可以存新的值的坑
                int x = arr[i];
                int j = i - 1;
                //在前面有一个或连续多个值比x大的时候,一直循环往前面找,将x插入到这串值前面
                while (j >= 0 && arr[j] > x) {
                    //当arr[j]比x大的时候,将j向后移一位,正好填到坑中
                    arr[j + 1] = arr[j];
                    j--;
                }
                //将x插入到最前面
                arr[j + 1] = x;
            }
        }
}

六、希尔排序nlogn

Java中层级排序 java底层排序算法_java_04

/**
     * 希尔排序
     *
     * @param array
     * @return
     */
    public static int[] ShellSort(int[] array) {
        int len = array.length;
        int temp, gap = len / 2;
        while (gap > 0) {
            for (int i = gap; i < len; i++) {
                temp = array[i];
                int j= i - gap;
                while (j>= 0 && array[j] > temp) {
                    array[j+ gap] = array[j];
                    j-= gap;
                }
                array[j+ gap] = temp;
            }
            gap /= 2;
        }
        return array;
    }

七、堆排序nlogn

堆是完全二叉树:1.大顶堆,2.小顶堆

Java中层级排序 java底层排序算法_数据结构_05

//声明全局变量,用于记录数组array的长度;
static int len;
    /**
     * 堆排序算法
     *
     * @param array
     * @return
     */
    public static int[] HeapSort(int[] array) {
        len = array.length;
        if (len < 1) return array;
        //1.构建一个最大堆
        buildMaxHeap(array);
        //2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
        while (len > 0) {
            swap(array, 0, len - 1);
            len--;
            adjustHeap(array, 0);
        }
        return array;
    }
    /**
     * 建立最大堆
     *
     * @param array
     */
    public static void buildMaxHeap(int[] array) {
        //从最后一个非叶子节点开始向上构造最大堆
        for (int i = (len/2 - 1); i >= 0; i--) { //感谢 @让我发会呆 网友的提醒,此处应该为 i = (len/2 - 1) 
            adjustHeap(array, i);
        }
    }
    /**
     * 调整使之成为最大堆
     *
     * @param array
     * @param i
     */
    public static void adjustHeap(int[] array, int i) {
        int maxIndex = i;
        //如果有左子树,且左子树大于父节点,则将最大指针指向左子树
        if (i * 2 < len && array[i * 2] > array[maxIndex])
            maxIndex = i * 2;
        //如果有右子树,且右子树大于父节点,则将最大指针指向右子树
        if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex])
            maxIndex = i * 2 + 1;
        //如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
        if (maxIndex != i) {
            swap(array, maxIndex, i);
            adjustHeap(array, maxIndex);
        }
    }

八、归并排序nlogn

初始有n个长度为1的有序序列,两两归并,得到n/2个长度为2的有序序列,重复,直到排完

/**
     * 归并排序
     *
     * @param array
     * @return
     */
    public static int[] MergeSort(int[] array) {
        if (array.length < 2) return array;
        int mid = array.length / 2;
        int[] left = Arrays.copyOfRange(array, 0, mid);
        int[] right = Arrays.copyOfRange(array, mid, array.length);
        return merge(MergeSort(left), MergeSort(right));
    }
    /**
     * 归并排序——将两段排序好的数组结合成一个排序数组
     *
     * @param left
     * @param right
     * @return
     */
    public static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        for (int index = 0, i = 0, j = 0; index < result.length; index++) {
            if (i >= left.length)
                result[index] = right[j++];
            else if (j >= right.length)
                result[index] = left[i++];
            else if (left[i] > right[j])
                result[index] = right[j++];
            else
                result[index] = left[i++];
        }
        return result;
    }

九、快速排序

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
class Solution {
    public int[] getLeastNumbers(int[] arr, int k) {
        quick(arr,0,arr.length-1);
        return Arrays.copyOf(arr,k);
    }

    public void quick(int [] arr,int left,int right){
        if(left>=right) return;
         
        int j = part(arr,left,right);
        quick(arr,left,j-1);
        quick(arr,j+1,right);
    }

    public int part(int[] arr, int left,int right){
        int base = arr[left];
        int i = left;
        int j = right;
        while(i<j){
            while(i<j && arr[j]>=base){
                j--;
            }
            while(i<j && arr[i]<=base){
                i++;
            }
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        arr[left] = arr[j];
        arr[j] = base;
        return j;
    }
}