java 实现八大排序算法

冒泡排序

        通过对待排序序列从前往后,依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐向后移动。

public void bubbleSort(int[] a) {
    int tmp;
    boolean flag = false;
    for (int i = 0; i < a.length - 1; i++) {
        for (int j = 0; j < a.length - i - 1; j++) {
            if (a[j] > a[j + 1]) {
                 tmp = a[j];
                 a[j] = a[j + 1];
                 a[j + 1] = tmp;
                 flag = true;
            }
        }
        if (!flag) {
            break;
        } else {
            flag = false;
            System.out.println("第" + (i + 1) + "躺排序结果为:" + Arrays.toString(a));
        }
    }
}

选择排序

排序思想:

(1)第一次从a[0]~a[n-1]中选择最小值,与a[0]交换。

(2)第二次从a[1]~a[n-1]中选择最小值,与a[1]交换。

(3)第三次从a[2]~a[n-1]中选择最小值,与a[2]交换。

  ······

(i)第i次从a[i-1]~a[n-1]中选择最小值,与a[i-1]交换。

(n-1)第i次从a[n-2]~a[n-1]中选择最小值,与a[n-2]交换。

public void selectSort(int[] a) {
    for (int i = 0; i < a.length - 1; i++) {
        int minIndex = i;
        int min = a[i];
        for (int j = i + 1; j < a.length; j++) {
            if (min > a[j]) {
                min = a[j];
                minIndex = j;
            }
        }
        if (minIndex != i) {
            a[minIndex] =a[i];
            a[i] = min;
        }
        System.out.println("第" + (i + 1) + "轮排序结果为:" + Arrays.toString(a));
    }
}

 插入排序

基本思想:将n个待排序的元素看成为一个有序表和一个无序表,开始时,有序表中只包含一个元素,无序表中包含n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之称为新的有序表。

public void insertSort(int[] a) {
    for (int i = 1; i < a.length; i++) {
        int insertValue = a[i];
        int insertIndex = i - 1;
        while (insertIndex >= 0 && insertValue < a[insertIndex]) {
            a[insertIndex + 1]  = a[insertIndex];
            insertIndex--;
        }
        if ((insertIndex + 1) != i) {
            a[insertIndex + 1] = insertValue;
        }
        System.out.println("第" + i + "轮排序结果为:" + Arrays.toString(a));
    }
}

希尔排序

基本思想:把记录按下标的一定增量进行分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法终止。

// 有序数据插入时采用交换法
public void shellSort(int[] a) {
    int tmp;
    int step = a.length / 2;
    int cnt = 0;
    while (step > 0) {
        for (int i = step; i < a.length; i++) {
            for (int j = i - step; j >= 0; j -= step) {
                if (a[j] > a[j + step]) {
                    tmp = a[j];
                    a[j] = a[j + step];
                    a[j + step] = tmp;
                }
            }
        }
        System.out.println("第" + (++cnt) + "轮排序结果为" + Arrays.toString(a));
        step /= 2;
    }
}

// 有序数据插入时采用移位法
public void shellSortByRemove(int[] a) {
    int tmp;
    int step = a.length / 2;
    int cnt = 1;
    while (step > 0) {
    // 从第step个元素开始,逐个对其所在的组进行直接插入排序
        for (int i = step; i < a.length; i++) {
            int insertIndex = i;
            int insertValue = a[insertIndex];
            if (a[insertIndex] < a[insertIndex - step]) {
                while (insertIndex - step >= 0 && insertValue < a[insertIndex - step]) {
                    a[insertIndex] = a[insertIndex - step];
                    insertIndex -= step;
                }
                a[insertIndex] = insertValue;
            }
        }
        System.out.println("第" + (cnt++) + "轮排序结果为" + Arrays.toString(a));
        step /= 2;
    }
}

  快速排序

基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个过程可以递归实现,以此达到整个数据变成有序序列。

public void quickSort(int[] a, int left, int right) {
    int r = right;
    int mid = a[(left + right) / 2];
    int tmp;
    while (l < r) {
        while(a[l] < mid) {
            l++;
        }
        while (a[r] > mid) {
            r--;
        }
        if (l >= r) {
            break;
        }
        tmp = a[l];
        a[l] = a[r];
        a[r] = tmp;
        // 交换完后,若a[l] == mid, r--,前移
        if (a[l] == mid) {
            r--;
        }
        if (a[r] == mid) {
            l++;
        }
    }
    // System.out.println(Arrays.toString(a));
    // 没有此判断,栈溢出
    if (l == r) {
        l++;
        r--;
    }
    if (left < r) {
        quickSort(a, left, r);
    }
    if (l < right) {
        quickSort(a, l, right);
    }
}

归并排序 

采用分治策略进行排序

 

public void mergeSort(int[] a, int left, int right, int[] tmp) {
    if (left < right) {
        int mid = (left + right) / 2;
        // 左递归分解
        mergeSort(a, left, mid, tmp);
        // 右递归分解
        mergeSort(a, mid + 1, right, tmp);
        merge(a, left, mid, right, tmp);
    }
    System.out.println(Arrays.toString(a));
}


public void merge(int[] a, int left, int mid, int right, int[] tmp) {
    int i = left;
    int j = mid + 1;
    int k  = 0;
    while(i <= mid && j <= right) {
        if (a[i] <= a[j]) {
            tmp[k++] = a[i++];
        } else {
            tmp[k++] = a[j++];
        }
    }
    while (i <= mid) {
        tmp[k++] = a[i++];
    }
    while (j <= right) {
        tmp[k++] = a[j++];
    }
    // tmp拷贝到a
    k = 0;
    int tmpLeft = left;
    while (tmpLeft <= right) {
        a[tmpLeft++] = tmp[k++];
    }
}

 基数排序

基本思想:基数排序是桶排序的扩展,将所有待比较数值统一为同样的数位长度,数位较短的数值前面补0。然后从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数值就变成了一个有序序列。

public void radixSort(int[] a, int max) {

    // 最大数的位数
    int maxLength = (max + "").length();

    // 桶
    int[][] bucket = new int[10][a.length];
    
    // 为了记录每个桶实际放了多少数据
    int[] bucketEleCnt = new int[10];

    for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
        for (int j : a) {
            int digit = j / n % 10;
            bucket[digit][bucketEleCnt[digit]++] = j;
        }
        // 按桶的数据将数据放入原来的数组
        int index = 0;
        for (int t = 0; t < bucketEleCnt.length; t++) {
            if (bucketEleCnt[t] > 0) {
                int k = 0;
                while (k < bucketEleCnt[t]) {
                    a[index++] = bucket[t][k++];
                }
            }
        bucketEleCnt[t] = 0;
        }
        System.out.println("第" + (i + 1) + "轮结果:" + Arrays.toString(a));
    }
}

 堆排序

后续更新

总结

n:数据规模

k:桶的个数

排序算法平均时间复杂度最好情况最坏情况空间复杂度是否占用额外内存稳定性10万个数据所需时间(ms)
冒泡排序O(n^{2})O(n)O(n^{2})O(1)稳定18165
选择排序O(n^{2})O(n^{2})O(n^{2})O(1)不稳定4048
插入排序O(n^{2})O(n)O(n^{2})O(1)稳定1445
希尔排序O(nlogn)O(nlog^{^{2}}n)O(nlog^{^{2}}n)O(1)不稳定

(交换法)10457

(移位法)26

归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定30
快速排序O(nlogn)O(nlogn)O(n^{2})O(nlogn)不稳定25
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
基数排序O(n\times k)O(n\times k)O(n\times k)O(n+ k)稳定20

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值