Bootstrap

算法五大排序(Java)

冒泡排序

思路:在一个数组中,将当前的索引的值与后一个做比较如果更大就交换,直到交换到最后一位。

详细实现:

第一个for循环控制总体遍历的次数。

为什么是判断条件是n - 1呢?因为只剩一个数的时候就不需要进行排序了。

第二个for循环是为了交换元素,比较大小,大的向后移动。

为什么要引入swaped变量呢?是一种优化思路,如果是个有序数组,就不用交换了。节约资源消耗。

public class Solution {
    public void bubbleSort(int[] arr, int n) {
        for (int i = 0; i < n - 1; i++) {
            boolean swaped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    swaped = true;                    
                }
            }
            if (!swaped) break;
        }
    }
}

插入排序

思路:模拟了整理扑克牌,分为两部分,左边是排好序的,右边是未排序的。遍历右边插入左边。

详细实现:第一个元素视为排好序的,for循环遍历右边数组。如果当前元素比已经排序好的元素大,正常插入到后面。如果小,移动已经排序好的元素,插入到正确位置。

public class Solution {
    public void insertSort(int[] arr, int n) {
        //从第二个元素开始,第一个元素视为已排序
        for (int i = 1; i < n; i++) {
            int j = i - 1;
            int value = arr[i];//当前要插入的元素
            while (j >= 0 && arr[j] > value) {
                arr[j + 1] = arr[j];元素右移
                j--;
            }
            arr[j + 1] = value;//插入正确位置
        }
    }
}

选择排序

思路:先选择一个数当最小值,遍历整个数组寻找最小值,如果比当前值小就交换。

详细实现:

外层for循环依然表示排序次数,因为一次可以确定一个最小值。

minIndex是最小值索引。

最后就是遍历和交换的步骤。

public class Solution {
    public void selectSort(int[] arr, int n) {
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            if (minIndex != i) {
                int tmp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = tmp;
            }
        }
    }
}

快速排序

思路:找一个基准数(通常用最后一个数),比他小的放到基数前,大的放在后面。

详细实现:递归实现排序,low<high表示还有元素需要排序。

把最后一个元素当作基数,循环遍历数组,如果找到比基数小的,交换当前元素和小于基数的索引位置。最后把基数放到正确的位置,即比基数小的索引加一。

public class Solution {
    public void quickSort(int[] arr, int n) {
        quickSortMethod(arr, 0, n - 1);
    }
    private void quickSortMethod(int[] arr, int low, int high) {
        if (low < high) {
            int pivotIndex =  partition(arr, low, high);
            quickSortMethod(arr, low, pivotIndex - 1);
            quickSortMethod(arr, pivotIndex + 1, high);
        }
    }
    private int  partition(int[] arr, int low, int high) {
        int i = low - 1;
        int pivot = arr[high];
        for (int j = low; j < high; j++) {
            if (arr[j] < pivot) {
                i++;
                int tmp1 = arr[j];
                arr[j] = arr[i];
                arr[i] = tmp1;
            }
        }
        int tmp2 = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = tmp2;
        return i + 1;
    }
}

归并排序

思路:将数组一分为二,先排序两侧,在合并的时候排序整体

详细设计:

先计算中间的索引。进行递归,先分为左数组和右数组,将原数组中的数拷贝到左右数组中。

合并操作是判断左右两个数组中哪个元素更小,放到原数组中。

最后剩余元素拷贝回原数组。

public class Solution {
    public void mergeSort(int[] arr, int n) {
        if (n < 2) return;
        mergeSortMethod(arr, 0, n - 1);
    }
    private void mergeSortMethod(int[] arr, int left, int right) {
        if (left < right) {
            int mid = left + (right - left) / 2;
            mergeSortMethod(arr, left, mid);
            mergeSortMethod(arr, mid + 1, right);
            merge(arr, left, mid, right);
        }
    }
    private void merge(int[] arr, int left, int mid, int right) {
        int n1 = mid - left + 1;
        int n2 = right - mid;
        int[] leftArr = new int[n1];
        int[] rightArr = new int[n2];
        for (int i = 0; i < n1; i++) {
            leftArr[i] = arr[left + i];
        }
         for (int i = 0; i < n2; i++) {
            rightArr[i] = arr[mid + 1 + i];
        }

        int i = 0;
        int j = 0;
        int k = left;
        while (i < n1 && j < n2) {
            if (leftArr[i] <= rightArr[j]) {
                arr[k] = leftArr[i];
                i++;
            } else {
                arr[k] = rightArr[j];
                j++;
            }
            k++;
        }
        
        while (i < n1) {
            arr[k++] = leftArr[i++];
        }
        while (j < n2) {
            arr[k++] = rightArr[j++];
        }
    }
}

;