排序算法(冒泡、插入、希尔、快速、归并、选择)& 时空复杂度 & Java 排序算法实现

零、写在前面

  • 稳定性是指相等的元素经过排序之后相对顺序是否发生了改变

一、冒泡排序(稳定)

  • 时间复杂度(平均):O( n 2 n^2 n2)
  • 时间复杂度(最优):O(n)
  • 时间复杂度(最差):O( n 2 n^2 n2)
  • 空间复杂度:O(1)
package cn.edu.neu.argorithm.sorter;

import java.util.Arrays;

/**
 * @author 32098
 *
 * 冒泡排序
 */
public class BubbleSorter {
    /**
     * 升序排序
     * @param a a
     * @param <T> T
     */
    public static <T extends Comparable<? super T>> void bubbleSort (T[] a) {
        int pass = 1;
        boolean exchange = true;
        while(pass < a.length && exchange) {
            exchange = bubbleExchange(a, pass);
            pass++;
        }
    }

    /**
     *
     * @param a a
     * @param i i
     * @param <T> T
     * @return exchange
     */
    private static <T extends Comparable<? super T>> boolean bubbleExchange(T[] a, int i){
        // 交换标志置为 false 表示未交换
        boolean exchange = false;
        for ( int j = 0; j<a.length-i;  j++ ) {
            if (a[j].compareTo(a[j+1])>0){
                T temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
                exchange = true;
            }
        }
        return exchange;
    }

    /**
     * 降序排序
     * @param a a
     * @param <T> T
     */
    public static <T extends Comparable<? super T>> void bubbleSortDesc (T[] a) {
        T tmp;
        for(int i=0; i<a.length; i++){
            boolean exchange = false;
            for(int j=1; j<a.length-i; j++){
                if(a[j].compareTo(a[j-1])>0){
                    tmp = a[j-1];
                    a[j-1] = a[j];
                    a[j] = tmp;
                    exchange = true;
                }
            }
            // 未交换直接退出排序
            if(!exchange){
                break;
            }
        }
    }

    public static void main(String[] args) {
        Integer[] a={49, 38, 65, 97, 76, 13, 27, 49};
        bubbleSort(a);
        System.out.println(Arrays.asList(a));
        a= new Integer[]{49, 38, 65, 97, 76, 13, 27, 49};
        bubbleSortDesc(a);
        System.out.println(Arrays.asList(a));
    }
}

在这里插入图片描述

二、插入排序(稳定)

  • 时间复杂度(平均):O( n 2 n^2 n2)

  • 时间复杂度(最优):O(n)

  • 时间复杂度(最差):O( n 2 n^2 n2)

  • 空间复杂度:O(1)
    在这里插入图片描述

package cn.edu.neu.argorithm.sorter;

/**
 * @author 32098
 *
 * 简单插入排序
 */
public class InsertionSorter {
    public static <T extends Comparable<? super T>> void insertionSort(T[] a){
        // i 初始为 1 是默认数组 a 的 第一个元素 a[0] 已插入
        for (int i = 1; i < a.length; i++) {
            insert(a, i);
        }
    }

    private static <T extends Comparable<? super T>> void insert(T[] a, int i) {
        T insertItem = a[i];
        // 从后向前比较
        int j = i;
        while(j-1>=0 && insertItem.compareTo(a[j-1])<0){
            a[j] = a[j-1];
            j--;
        }
        a[j] = insertItem;
    }

    public static void main(String[] args) {
        Integer[] a={49, 38, 65, 97, 76, 13, 27, 49};
        insertionSort(a);
        for (Integer integer : a) {
            System.out.println(integer);
        }
    }
}

三、希尔排序-增量递减排序(不稳定)

增量+插入排序

  • 时间复杂度(平均):O( n 3 / 2 n^{3/2} n3/2) \ O( n l o g 2 n n log^2 n nlog2n) (取决于间距序列的选取)
  • 时间复杂度(最优):O(n)
  • 时间复杂度(最差):O( n 3 / 2 n^{3/2} n3/2) \ O( n l o g 2 n n log^2 n nlog2n) (取决于间距序列的选取)
  • 空间复杂度:O(1)

在这里插入图片描述
2.
在这里插入图片描述

package cn.edu.neu.argorithm.sorter;

/**
 * @author 32098
 *
 * 希尔排序
 */
public class ShellSorter {
    public static <T extends Comparable<? super T>> void shellSort (T[] a) {
        int gap = a.length/2;
        // gap 是子序列间隔
        while (gap!=0) {
            // 插入排序
            shellInsert(a, gap);
            // gap=gap/2
            gap = (gap == 2) ? 1 : (int) ( gap/2.2 );
        }
    }

    private static <T extends Comparable<? super T>> void shellInsert (T[] a, int gap ) {
        for (int i = gap; i < a.length; i++) {
            T insertItem = a[i];
            int j = i;
            while(j-gap>=0 && insertItem.compareTo(a[j-gap])<0){
                a[j] = a[j-gap];
                j = j-gap;
            }
            a[j] = insertItem;
        }
    }

    public static void main(String[] args) {
        Integer[] a={91, 67, 35, 62, 29, 72, 46, 57};
        shellSort(a);
        for (Integer integer : a) {
            System.out.println(integer);
        }
    }
}

四、快速排序(不稳定)

  • 时间复杂度(平均):O(n logn)

  • 时间复杂度(最优):O(n logn)

  • 时间复杂度(最差):O( n 2 n^2 n2)

  • 空间复杂度:O(logn)

  • 选择基准点
    在这里插入图片描述

  • 与第一个元素交换
    在这里插入图片描述

  • 遍历数组,交换小的数到swapPos
    在这里插入图片描述
    在这里插入图片描述

package cn.edu.neu.argorithm.sorter;

import java.util.Arrays;

/**
 * @author 32098
 *
 * 快速排序:
 * 1. pivot
 */
public class QuickSorter {
	public static<T extends Comparable<? super T>> void quickSort(T[] a) {
		quickSort(a,0,a.length-1);
	}

	private static<T extends Comparable<? super T>> void quickSort(T[] a, int left, int right) {
		if(left<right) {
			int pivotPos = partition(a, left, right);
			// 左子区间递归快排
			quickSort(a, left, pivotPos-1);
			// 右子区间递归快排
			quickSort(a, pivotPos+1, right);
		}
	}

	private static<T extends Comparable<? super T>> int partition(T[] a, int low, int high) {
		int swapPos=low;
		// 交换数组中间的元素到第一个元素,并作为基准点
		swap(a, low, (low+high)/2);
		T pivot=a[low];
		// 小于基准点的元素放到左边、大于基准点的元素放到右边
		for(int i=low+1; i<=high; i++) {
			if(a[i].compareTo(pivot)<0) {
				swapPos++;
				swap(a, swapPos, i);
			}
		}
		swap(a, low, swapPos);
		return swapPos;
	}

	private static<T extends Comparable<? super T>> void swap(T[] a, int swapA, int swapB) {
		T temp=a[swapA];
		a[swapA]=a[swapB];
		a[swapB]=temp;
	}
	
	

	public static void main(String[] args) {
		Integer[] a={5,11,4,25,10,3,9,15,12};
		QuickSorter.quickSort(a);
		System.out.println(Arrays.asList(a));
		a = new Integer[]{5, 11, 4, 25, 10, 3, 9, 15, 12};
	}
}

五、归并排序(稳定)

  • 时间复杂度(平均):O(n logn)
  • 时间复杂度(最优):O(n logn)
  • 时间复杂度(最差):O(n logn)
  • 空间复杂度:O(n)
    在这里插入图片描述
    在这里插入图片描述
package cn.edu.neu.argorithm.sorter;

import java.util.Arrays;

/**
 * @author 32098
 */
public class MergeSorter {
    private static <T extends Comparable<? super T>> void merge (T[] initList, T[] mergedList, int l,  int m, int n ) {
        int i = l, j = m + 1, k = l;
        while (i <= m && j <= n) {
            if (initList[i].compareTo(initList[j]) <= 0) {
                mergedList[k] = initList[i];
                i++;
                k++;
            } else {
                mergedList[k] = initList[j];
                j++;
                k++;
            }
        }
        if (i <= m) {
            while (i <= m) {
                mergedList[k++] = initList[i++];
            }
        } else {
            while (j <= n) {
                mergedList[k++] = initList[j++];
            }
        }
    }

    private static <T extends Comparable<? super T>> void mergePass (T[] initList, T[] mergedList, int len ) {
        int i =0;
        while ( i+2*len <= initList.length) {
            merge(initList,  mergedList,  i,  i+len-1,
                    i+2*len-1);
            i = i + 2*len;
        }
        if ( i+len <= initList.length-1 ) {
            merge ( initList,  mergedList,  i,  i+len-1,
                    initList.length-1 );
        } else {
            for (int j = i; j <= initList.length-1; j++ ) {
                mergedList[j] = initList[j];
            }
        }
    }

    public static <T extends Comparable<? super T>> void mergeSort(T[] list) {
        T[] tempList = Arrays.copyOf(list, list.length);
        int len = 1;
        while ( len < list.length ) {
            mergePass ( list, tempList, len );   len *= 2;
            mergePass ( tempList, list, len );   len *= 2;
        }
    }

    public static void main(String[] args) {
        Integer[] a={5,11,4,25,10,3,9,15,12};
        MergeSorter.mergeSort(a);
        System.out.println(Arrays.asList(a));
    }
}


六、选择排序(不稳定)

  • 时间复杂度(平均):O( n 2 n^2 n2)
  • 时间复杂度(最优):O( n 2 n^2 n2)
  • 时间复杂度(最差):O( n 2 n^2 n2)
  • 空间复杂度:O(1)
    在这里插入图片描述
package cn.edu.neu.argorithm.sorter;

/**
 * @author 32098
 */
public class SelectionSorter {
    private static <T extends Comparable<? super T>> void selectSort (T[] a) {
        for(int i = 0; i < a.length-1; i++) {
            selectExchange (a, i);
        }
    }

    private static <T extends Comparable<? super T>> void selectExchange (T[] a, int i) {
        // k: min index
        int k = i;
        for ( int j = i+1; j < a.length; j++) {
            if (a[j].compareTo(a[k])<0) {
                k = j;
            }
        }
        if (k != i) {
            T temp = a[i];
            a[i] = a[k];
            a[k] = temp;
        }
    }

    public static void main(String[] args) {
        Integer[] a={91, 67, 35, 62, 29, 72, 46, 57};
        selectSort(a);
        for (Integer integer : a) {
            System.out.println(integer);
        }
    }
}

七、堆排序(不稳定)***:略

优先权队列

  • 降序使用小堆
  • 升序使用大堆

八、基数排序(稳定)***:略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值