常见的7种排序算法

package others.testCode;
import sort.ArrayList;
import java.util.Arrays;

/**
 * @Author Linton
 * @Date 2019/7/9 15:05
 * @Email lintonhank@foxmail.com
 * @Version 1.0
 * @Description
 */

public class WaysSort {
    public static void main(String[] args) {
        int[] ar = {23,15,37,89,2,21,43,9,56,0,1,22};
        WaysSort waysSort = new WaysSort();
        System.out.println(Arrays.toString(ar));
//        waysSort.quickSort(ar, 0, ar.length-1); // 快速排序
//        waysSort.BubbleSort(ar); // 冒泡排序
//        waysSort.choiceSort(ar); // 选择排序
//        waysSort.InsertSort(ar,1); //插入排序
//        waysSort.shellSort(ar);    // 希尔排序
        waysSort.mergeSort(ar);
        System.out.println(Arrays.toString(ar));
//        ArrayList.display(ar);
    }

一、快速排序

快速排序:取数组中一个关键字作为划分枢纽,划分成左右两个子数组,较小值在左侧,较大值在右侧;在左右子数组中重复上述操作,即递归的调用自身为每一个子数组进行快速排序,直到子数组只包含一个数据项,此时数组已有序
算法实现思路: n个数的数组,选定最左边的值为枢纽值,左右两边设置移动指针i,j;先从右端开始,把找到小于枢纽值的数,再去左边找到大于枢纽值的数,通过移动指针 i,j交换这两个数的位置,依次进行,知道i=j,即划分算法(荷兰国旗问题)。分开的两个子数组分别递归使用quickSort

    void quickSort(int[] arr, int left, int right){
        if (left >= right)
            return;
        int i = left; int j = right; int pivot = arr[i]; // 取最左边的值为枢纽值
        while (i < j){                      // i == j 时,跳出循环
            // 从右端开始,发现小于枢纽值,替换到左边的指针处
            while (i < j && arr[j] >= pivot){ // 向左寻找第一个小于index的数
                j--;
            }
            if (i < j) {
                arr[i++] = arr[j];  // 将array[j]填入array[i],并将i向右移动!!!
            }
            // 从左端开始,发现大于枢纽值,替换到右边的指针处
            while (i < j && arr[i] <= pivot) { // 向右寻找第一个大于index的数
                i++;
            }
            if (i < j) {
                arr[j--] = arr[i];   //将array[i]填入array[j],并将j向右移动!!!
            }
        }
        // partition完毕,分开的两个子数组分别递归使用quickSort
        arr[i] = pivot;  // 将枢纽值放入最终位置
        quickSort(arr, left, i - 1);
        quickSort(arr, i + 1, right);
    }

二、冒泡排序

冒泡排序(每次循环,每相邻的两个数都需要比较):n个数的数组比较大小,循环n次,每一次循环,通过比较相邻的两个数,较大者放在后面,依次进行,最大值会移动到数组末尾。循环n次,则得到排好序的数组

    void BubbleSort(int[] arr){  // for(for(if))
        for(int i = 0; i < arr.length  ; i++){
            for (int j = 0; j < arr.length - i - 1 ; j++){
                if (arr[j] > arr[j + 1]){
                    int tmp = arr[j + 1];
                    arr[j + 1] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
    }

三、选择排序

选择排序:n个数的数组,循环n次,在每一次循环中,比较出最小的数值,把最小的数值和数组第一个数交换位置。在接下来的循环中,排除已经排好序的部分,使用相同的方式得出数组未排序部分的最小值。循环结束,则得到排好序的数组。

    void choiceSort(int[] arr){   // for(for、if)
        for (int i = 0 ; i < arr.length; i++) {
            int index =  i;
            for (int j = i + 1; j < arr.length; j++) {
                if(arr[index] > arr[j]){
                    index = j;
                }
            }
            if (index == i){
                continue;
            } else {
                int tmp = arr[index];
                arr[index] = arr[i];
                arr[i] = tmp;
            }
        }
    }

四、插入排序

插入排序(类似打扑克摆牌):基本思想就是将无序序列插入到有序序列中。从第二个元素开始,将当前元素插入到前面对应位置,使当前元素i和之前的元素形成有序数组,依次进行。

    void InsertSort(int[] arr, int h) { // for(if(for))
         h = 1;
        for (int i = h; i < arr.length; i++){
            int j;
            if (arr[i] < arr[i - h]) {
                int tmp = arr[i];   //保存当前数值(即待插入的数)
                for (j = i - h; j >= 0 && tmp < arr[j]; j -= h){
                    arr[j + h] = arr[j];   // 数值复制到后一位,给新的值留出空
                }
                arr[j + h] = tmp;
            }
        }
    }
/*    void InsertSort(int[] arr) { // for(if(for))
        for (int i = 1; i < arr.length; i++){
            int j;
            if (arr[i] < arr[i - 1]) {
                int tmp = arr[i];   //保存当前数值(即待插入的数)
                for (j = i - 1; j >= 0 && tmp < arr[j]; j--){
                    arr[j + 1] = arr[j];   // 数值复制到后一位,给新的值留出空
                }
                arr[j + 1] = tmp;
            }
        }
    }*/

五、希尔排序

希尔排序(基于插入排序):先将待排记录序列分割成为若干子序列分别进行插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序。

    void shellSort(int[] arr) {
        int i ; int j;
        long tmp;

        int h = 1;
        while (h <= arr.length/3) {  // 求解增量h
            h = h * 3 + 1;
        }
        while (h > 0) {
            // 插入排序的循环使用
            InsertSort(arr, h);
            h = (h - 1)/3;
        }

    }
}

六、归并排序

归并排序:把一个数组分成两半,排序每一半,然后利用merge()方法把数组的两半归并成一个有序的数组。而每一半的排序,递归使用归并排序。

   void mergeSort(int[] arr) {
        int [] temp = new int[arr.length];  // 构造辅助数组
        recMerge(arr, 0 , arr.length - 1, temp);

    }
    void  recMerge(int[] arr, int lowerBound, int upperBound, int[] temp ){
        if (lowerBound == upperBound){  //递归结束条件,分组只有一个数字时,认为有序,返回
            return;
        }else {
            int mid = (lowerBound + upperBound) / 2;
            recMerge(arr, lowerBound, mid, temp);                       // 排序左半数组
            recMerge(arr, mid + 1, upperBound, temp);        // 排序右半数组
            merge(arr, lowerBound, mid + 1, upperBound, temp); // 合并两个数组
        }
    }
    // 合并两个数组
    void merge(int[] arr, int lowPtr, int higthPtr, int upperBound, int[] temp) {
        int n = 0;     //辅助数组的索引
        int start = lowPtr;     //保存 辅助数组数据放回原数组时的 起始点
        int mid = higthPtr - 1; // lowPtr 左数组下边界,mid 左数组上边界; hightPtr(mid+1) 右数组下边界,upperBound 右数组上边界

        while (lowPtr <= mid && higthPtr <= upperBound){  //第一个while循环:沿左右数组走,比较他们的数据项,复制较小的数据到辅助数组
            if (arr[lowPtr] < arr[higthPtr]){
                temp[n++] = arr[lowPtr++];
            } else {
                temp[n++] = arr[higthPtr++];
            }
        }

        while (lowPtr <= mid) {            //第二个while循环:右数组先遍历完,左数组剩余数据项直接复制到辅助数组
            temp[n++] = arr[lowPtr++];
        }
        while (higthPtr <= upperBound){  //第三个while循环:左数组先遍历完,右数组剩余数据项直接复制到辅助数组
            temp[n++] = arr[higthPtr++];
        }

//        把辅助数组的数据放到原空间
        for (int i = 0; i < n ;i++){
            arr[start + i] = temp[i];
        }
    }

七、堆排序

// 未完待续
// 堆排序
// 基数排序

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值