码迷,mamicode.com
首页 > 编程语言 > 详细

基础的排序算法

时间:2021-07-29 16:19:56      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:频繁   最大的   array   --   简单   序列   两个指针   算法   元素   

简单梳理一下以前学过的排序算法

冒泡排序

平均时间复杂度:O(n2);稳定

  1. 比较相邻元素,如果前面的比后面大,就交换两个元素
  2. 每一对相邻元素做同样的比较,从开始第一对元素一直比到结尾,一轮结束最后的元素是最大的。
  3. 除了每轮比较出来的最大元素,对其他元素重复以上操作。
	public void bubbleSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array.length - 1; j++) {
                if (array[j + 1] < array[j]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }

选择排序

平均时间复杂度:O(n2);不稳定

  1. 在所有元素中选取最小的元素,放在第一个位置。
  2. 在剩余元素里选取最小的元素,放在第二个位置。
  3. 以此类推
	public void selectionSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i; j < array.length; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            int temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
    }

插入排序

平均时间复杂度:O(n2);稳定

  1. 以第一个元素为有序序列,从末尾开始比较,即要插入的元素和已经有序的最大者开始比起。
  2. 如果比它大则插入后面,否则一直比较,直到找到它该插入的位置。
  3. 如果遇到的元素和要插入的元素相等,那么要插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,所以插入排序是稳定的。
	public void insertionSort(int[] array) {
        int current;
        for (int i = 0; i < array.length - 1; i++) {
            current = array[i + 1];
            int preIndex = i;
            while (preIndex >= 0 && current < array[preIndex]){
                array[preIndex + 1] = array[preIndex];
                preIndex--;
            }
            array[preIndex + 1] = current;
        }
    }

希尔排序

平均时间复杂度:O(nlog?n);不稳定

希尔排序又叫做最小增量排序,将整个待排序的序列分割成为若干子序列,分别进行插入排序。

  1. 选择增量 gap=length/2,这种增量选择可以用一个序列来表示,{n/2, (n/2)/2, ... 1},称为增量序列。
  2. 对每个子序列进行插入排序后,缩小增量继续以 gap = gap/2 的方式执行。
	public void 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 preIndex = i - gap;
                while (preIndex >= 0 && array[preIndex] > temp) {
                    array[preIndex + gap] = array[preIndex];
                    preIndex -= gap;
                }
                array[preIndex + gap] = temp;
            }
            gap /= 2;
        }
    }

归并排序

分治法的典型应用。始终都是 O(nlogn) 的时间复杂度,代价是需要额外的内存空间。

平均时间复杂度:O(nlogn);稳定

  1. 将长度为 n 的序列分成两个长度为 n/2 的子序列;
  2. 分别对子序列采用归并排序;
  3. 将两个排序好的子序列合并成一个有序序列;
 	public void sort(int[] array) {
        //在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间
        int[] temp = new int[array.length];
        sort(array, 0, array.length - 1, temp);
    }

    public void sort(int[] array, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left + right) / 2;
            sort(array, left, mid, temp);	//左边归并排序,使得左子序列有序
            sort(array, mid + 1, right, temp);//右边归并排序,使得右子序列有序
            merge(array, left, mid, right, temp);//将两个有序子数组合并操作
        }
    }

	public void merge(int[] array, int left, int mid, int right, int[] temp){
        int i = left;	//左序列指针
        int j = mid + 1;	//右序列指针
        int t = 0;	//临时数组指针
        while (i <= mid && j <= right) {
            if (array[i] <= array[j]) {
                temp[t++] = array[i++];
            } else {
                temp[t++] = array[j++];
            }
        }
        while (i <= mid) {//将左边剩余元素填充进temp中
            temp[t++] = array[i++];
        }
        while (j <= right) {//将右序列剩余元素填充进temp中
            temp[t++] = array[j++];
        }
        t = 0;
        //将temp中的元素全部拷贝到原数组中
        while (left <= right) {
            array[left++] = temp[t++];
        }
    }

快速排序

平均时间复杂度:O(nlogn);不稳定

  1. 在序列中选一个基准数(pivot),一般选首位置元素为基准。
  2. 快排利用两个指针,分别设为左left,右right,双向进行。比基准数大的放右边,比基准数小的放左边,当left < right 时,遍历结束。
  3. 利用递归,把比基准小的子序列、比基准大的子序列分别重复上述排序步骤。
    public void quickSort(int[] array, int left, int right) {
        if (left < right) {
            int index = getIndex(array, left, right);
            quickSort(array, left, index - 1);
            quickSort(array, index + 1, right);
        }
    }

    public int getIndex(int[] array, int left, int right) {

        int pivot = array[left];
        
        while (left < right) {
            while (left < right && array[right] >= pivot) {
                right--;
            }
            array[left] = array[right];

            while (left < right && array[left] <= pivot) {
                left++;
            }
            array[right] = array[left];
        }
        array[right] = pivot;
        return right;
    }

    public void quickSort(int[] array) {
        quickSort(array, 0, array.length - 1);
    }

堆排序

有点遗忘,回头补上

基础的排序算法

标签:频繁   最大的   array   --   简单   序列   两个指针   算法   元素   

原文地址:https://www.cnblogs.com/leejk/p/15068383.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有
迷上了代码!