• 排序算法总结


    排序算法

    大部分算法都是从无序区扩展到有序区

    一、算法概述

    1.冒泡排序 O(N2),空间O(1)

    每一轮从无序区冒泡出一个最大的数到有序区

    2.选择排序O(N2),空间O(1)

    每一轮从无序区选择一个最大的数到有序区

    3.堆排序O(NlogN),空间O(1)

    其实就是选择排序的改进,每次从堆中选择一个最大值;

    堆:父节点的值 >= 所有子节点的值

    建堆:

    在一个数组中,下标为0的元素为根节点,i的子节点为2i+1和2i+2;

    从右往左、从下往上的第一个非叶子节点开始,即arr.length/2-1,与它的子节点递归比较。

    建完堆后,产生一个最大值,将它与最后一个节点swap,无序区就变成了N-1,这个时候只要将根节点递归比较,就能产生次大值,依次下去...

    public class HeapSort {
    	public static void main(String[] args) {
    		int[] array = new int[] { 2, 1, 4, 3, 6, 5, 8, 7 };
    		// 接下来就是排序的主体逻辑
    		sort(array);
    		System.out.println(Arrays.toString(array));
    	}
    public static void sort(int[] array) {
    	
    	for (int i = array.length / 2 - 1; i >= 0; i--) {
    		adjustHeap(array, i, array.length);
    	}
     
    
    	for (int j = array.length - 1; j > 0; j--) {
    
    		adjustHeap(array, 0, j);
    	}
    }
    
    public static void adjustHeap(int[] array, int i, int length) {
    
    	int temp = array[i];
    
    	for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
    
    		if (k + 1 < length && array[k] < array[k + 1]) {
    			k++;
    		}
    
    		if (array[k] > temp) {
    			swap(array, i, k);
    			
    			i = k;
    
    		} else {
    			break;
    		}
    	}
    }
    
    public static void swap(int[] arr, int a, int b) {
    	int temp = arr[a];
    	arr[a] = arr[b];
    	arr[b] = temp;
    }
    }
    

    4.插入排序O(N2),空间O(1)

    在数组大多数元素有序时有优势

    从第2个元素开始,与前面的元素比较,若小于前面的,则swap,注意要向前比较一直到不用swap。

    5.希尔排序O(?),空间O(1)

    假定一个数k,如果说插入排序每次是与前面间隔1步的比较,那么希尔排序就是与前面间隔k步的比较

    k每轮减1,一直到1,这样做其实利用插入排序的优势。

    6.归并排序O(NlogN),空间O(N)

    分治,O(N)合并

    7.快速排序O(NlogN),空间O(logN)

    主要难写的就是划分区域的部分
    

    划分为左区域、右区域,先从右边扫,再从左边扫

    (各扫到一个不满足条件的数后,交换,进行下一轮)

       temp = a[left]; //temp中存的就是基准数
        i = left;
        j = right;
        while(i != j) { //顺序很重要,要先从右边开始找
        	while(a[j] > temp && i < j)
        		j--;
        	while(a[i] <= temp && i < j)//再找左边的
        		i++;       
        	if(i < j)//交换两个数在数组中的位置
        	{
        		t = a[i];
        		a[i] = a[j];
        		a[j] = t;
        	}
        }
        //最终将基准数归位
        a[left] = a[i];
        a[i] = temp;
    
    

    为啥这个做法是正确的?

    分情况讨论一下即可:

    两边若都扫到一个不满足a[j] > temp/<= temp 条件的,则交换;

    右边是一定会扫到,而左边没扫到,则可以停止了,最终将基准数归位。

    8.桶排序O(N),空间O(M)

    桶即hash的那个桶

    • 计数排序

      数字区间范围小的,比如年龄、身高

    • 基数排序

      以数字为0-9作为桶,从低位到高位排

  • 相关阅读:
    关于代码的一系列调整
    题目清单(更新至2016年12月17日 10:52)
    USACO翻译:USACO 2013 NOV Silver三题
    USACO翻译:USACO 2013 DEC Silver三题
    USACO翻译:USACO 2014 DEC Silver三题
    USACO翻译:USACO 2012 FEB Silver三题
    USACO翻译:USACO 2012 JAN三题(3)
    USACO翻译:USACO 2012 JAN三题(2)
    USACO翻译:USACO 2012 JAN三题(1)
    USACO翻译:USACO 2014 FEB SILVER 三题
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/11183847.html
Copyright © 2020-2023  润新知