首页 > 代码库 > 数组排序算法

数组排序算法

  前几天浏览网页,看到过一个帖子,问:

  有哪些算法惊艳到了你?

  下面有100多的回答,浏览了一些,有的是根本没听过,涉及到了多个领域的优秀算法,其中有一个回答是快排,而且还有很生动的动图演示。

  后来做算法题时,就遇到了数组排序的问题,再去那网页找那个快排时,就没再看到那个动图TOT,可能是太多回答我没找太细,这里留一下网址:https://www.zhihu.com/question/26934313。

  没找到后悔不已啊,只能自己百度去找相关详细的介绍了。

  下面记录一下数组排序的几种方法:

1、最简单方便使用的就是 Arrays 自带的 Arrays.sort(array);这里不过多描述。

import java.util.Arrays;

public class SortTest {
    public static void main (String[] args) {
        int[] arr = new int[10];
        for(int i = 0; i < arr.length; i ++) {
            arr[i] = (int)(Math.random()*100);
        }
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

 

2、冒泡排序

  这个想必大家学语言的都学习过,当初脑子笨,逻辑不好,还记了好久才读懂原理,还好现在回想起来还是很简单的,不知道什么时候脑袋就开窍了,哈哈。

  它的原理嘛,就是遍历数组,然后比较两个数的值的大小,来将最小或者最大的数置换到最左边或者最右边。

  下面来记录方法:

public void bubbleSort (int[] numArr) {
    for(int i = 0; i < numArr.length - 1; i ++) {
        for(int j = i + 1; j < numArr.length; j ++) {
            if(numArr[i] > numArr[j]) {
                numArr[i] = numArr[i] + numArr[j];
                numArr[j] = numArr[i] - numArr[j];
                numArr[i] = numArr[i] - numArr[j];
            }
        }
    }
}

  外层循环整个数组元素,内层则循环下标 +1 的数,然后比较大小,通过每次其余元素与当前外层循环的元素比较,将当前比较出的较小数保存到外层下标处。拿方法中的第一次循环来说:0 下标会循环与其他下标的元素值进行比较,如果 0 下标数小,则不动,如果 0 下标数大,那么就将 0 下标数与比较下标数值互换,达到外层循环的 0 下标存储的值始终是较小的值,这样,内层循环完毕后,0 下标存储的值就会变成整个数组元素的最小值。

 

3、选择排序

  这种排序也是遍历寻找最小或者最大的值,然后单提出来存储到一个最小或最大值变量中,做排序题时,忘了诸多排序方法,只能自己想出一个最笨的方法,结果居然也有名字:选择排序。

public void selectSort (int[] numArr) {
    int minSub;
    boolean isChange;
    for(int i = 0; i < numArr.length; i ++) {
        isChange = false;
        minSub = i;
        for(int j = i + 1;j < numArr.length; j ++) {
            if(numArr[minSub] > numArr[j]) {
                isChange = true;
                minSub = j;
            }
        }
        if(isChange) {
            numArr[minSub] = numArr[i] + numArr[minSub];
            numArr[i] = numArr[minSub] - numArr[i];
            numArr[minSub] = numArr[minSub] - numArr[i];
        }
    }
}

  这个排序的思路是最简单易懂的:感觉有点类似冒泡的感觉,只不过多一个变量来进行存储最大或最小的值。比如当前方法:将 0 下标元素值当成最小值进行下标存储,然后遍历其后元素,寻找小于当前存储的变量值的元素,如果有,则对其下标进行存储,直到内层循环完成后,将存储的最小值下标与当前 0 下标值互换。最终得到升序排序的数组。

 

4、插入排序

  简单理解,就是将一个数据插入到已经排好序的有序数组中,从而得到一个新的,个数 +1 的数组。核心思想就是将数组分成两部分,一部分包含了数组所有元素,将最后一个元素除外;第二部分就只有一个元素。而后第一部分排序完成后,再将最后元素插入到已排好序的第一部分中。

public void insertSort () {
    for(int i = 1; i < numArr.length; i ++) {
        for(int j = i; j > 0; j --) {
            if(numArr[j - 1] > numArr[j]) {
                numArr[j - 1] = numArr[j - 1] + numArr[j];
                numArr[j] = numArr[j - 1] - numArr[j];
                numArr[j - 1] = numArr[j - 1] - numArr[j];
            }
        }
    }
}

  首先将数组分成两个部分,一部分有序,另一部分无序。看方法:首次循环,第一部分其实是没有的,直到找到最小值压入 0 下标位置,第一部分才形成,之后每次循环都将当次循环的下标值当成待排数,而后通过遍历已经排好的数组,判断该值是否大于前数,如果大于就前移一位,如果不大于,则不动,放置有序数组的最后一位。

  这个也还好理解吧?

 

5、快速排序

  据说是效率最快的,不过不如其它排序方法稳定,有可能相同值会有多次相对位置变动,因为它的大致实现是:

  选择一个标志值(通常为数组第一个元素),根据这个标志值同时从前后遍历查找大于或小于该值的数,将数组分成小于标志值和大于标志值两部分,经过一次快排后,左边为小于标志值元素,右边为大于标志值数,接着左右两边分别再进行快排,重复刚开始的步骤。最后直到变成有序数组。

public void quickSort (int firstSub, int lastSub) {
    int i = firstSub;
    int j = lastSub;
    int key = numArr[i];
        
    while(i < j) {
        while(i < j && numArr[j] >= key)
        j--;
            
        if(i < j){
            numArr[i] = numArr[i] + numArr[j];
            numArr[j] = numArr[i] - numArr[j];
            numArr[i] = numArr[i] - numArr[j];
            i++;
        }
            
        while(i < j && numArr[i] <= key)
        i++;
            
        if(i < j){
            numArr[j] = numArr[i] + numArr[j];
            numArr[i] = numArr[j] - numArr[i];
            numArr[j] = numArr[j] - numArr[i];
            j--;
        }
    }
    if(i > firstSub)quickSort(firstSub , i - 1);
    if(j < lastSub)quickSort(i + 1, lastSub);
}

  这个有点复杂,得仔细理解一下~

数组排序算法