插入、希尔、快排、堆排、归并

常用排序算法

1、冒泡排序

冒泡排序每次都将数组中的相邻元素进行比较,每一趟排序之后,都会有一个元素有序.

时间复杂度

最好平均最坏
O(n)O(n^2)O(n^2)
数据有序数据逆序

空间复杂度O(1)

稳定性稳定

 public static void bubbleSort(int[] array) {
        int len = array.length;
        for(int i = 0;i < len - 1;i++) {//比较趟数
            boolean flg = true;  //标记该躺是否发生交换
            for(int j = 0;j < len - 1 - i;j++) {  //每比较一次都有一个元素有序,减去i
                if(array[j] > array[j + 1]) {
                    flg = false;  //发生交换则改为false
                    int temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                }
            }
            //发生交换说明还有元素无序,没有发生交换说明已经有序,可以直接退出
            if(flg) {break;}
        }
        System.out.println("冒泡");
        System.out.println(Arrays.toString(array));
    }
2、选择排序

选择排序是最简单的排序,每次拿出一个元素与其余元素比较,然后交换.

时间复杂度O(n^2) 选择排序对数据不敏感,不管数据量多少,时间复杂度都是n^2

空间复杂度O(1)

稳定性不稳定

public static void selectSort(int[] array) {
    for(int i = 0;i < array.length;i++) {
        for(int j = i + 1;j < array.length;j++) {  //j从i+1开始
            if(array[j] < array[i]) {
                int temp = array[j];
                array[j] = array[i];
                array[i] = temp;
            }
        }
    }
}
3、插入排序

插入排序每次都把第一个元素当作有序,然后从后一个开始往回逐个比较排序。

时间复杂度

最好平均最坏
O(n)O(n^2)O(n^2)
数据有序数据逆序

空间复杂度O(1)

稳定性稳定

public static int[] insertSort(int[] array) {
    int pre = 0;
    int cur = 0;
    for(int i = 0;i < array.length - 1;i++) {
        cur = array[i + 1];  //默认前一个有序,取后一个
        pre = i;  //记住前一个下标
        while(pre >= 0 && cur < array[pre]) {  //后一个比前一个小则交换
            array[pre + 1] = array[pre];  //交换
            pre--;
        }
        //此时pre < 0,pre + 1位置赋值
        array[pre + 1] = cur; 
    }
    return array;
}
4、希尔排序

希尔排序与插入排序类似,不过希尔排序按照特定的步长进行插入排序。

时间复杂度

最好平均最坏
O(n)O(n^1.3)O(n^2)
数据有序较难构造

空间复杂度O(1)

稳定性不稳定

public static int[] shellSort(int[] array){
    int gap = array.length / 2;
    while(gap > 0) {
        for(int i = gap;i < array.length - 1;i++) {
            int cur = array[i];
            int pre = i - gap;
            while(pre >= 0 && cur < array[pre]) {
                array[pre + gap] = array[pre];
                pre -= gap;
            }
            array[pre + gap] = cur;
        }
        gap /=2;
    }
    return array;
}
5、快速排序

快速排序基于分治的思想,不断找基准。

时间复杂度

最好平均最坏
O(n*logn)O(n*logn)O(n^2)

空间复杂度

最好平均最坏
O(logn)O(logn)O(n)

稳定性不稳定

public static int[] quickSort(int[] array,int left,int right) {
    if(left < right) {
        int pov = partition(array,left,right);
        //递归
        quickSort(array,left,pov - 1);
        quickSort(array,pov + 1,right);
    }
    return array;
}

public static int partition(int[] array,int left,int right) {
    int key = array[left];  //默认左边为基准开始找
    while(left < right) {
        if(left < right && array[right] >= key) {right--}
        array[left] = array[right];
        if(left < right && array[left] <= key) {left++}
        array[right] = array[left];
    }
    array[left] = key;
    return left;
    
}
6、堆排序

堆排序先建堆,升序建最大堆,降序建最小堆

时间复杂度O(n*logn) 对数据不敏感

空间复杂度O(1)

稳定性不稳定
堆排序不了解的看之前写的博客 堆排序图解

public static void adjustDown(int[] array,int parent,int len) {  //向下调整
    int child = parent * 2 + 1;
    while(child < len) {  //是否有左孩子
        if(child + 1 < len && array[child + 1] > array[child]) {  //是否有右孩子并确定最大值
            child++;
        }
        //父亲节点比左右孩子最大值小,则交换
        if(array[parent] < array[child]) {
           	int temp = array[child];
            array[child] = array[parent];
            array[parent] = temp;
            //向下调整关键
            parent = child;
            child = parent * 2 + 1;
        }else {
            break;
        }
    } 
}

public static void createHeap(int[] array) {  //建堆,从最后一个父亲节点(非叶节点)开始向下调整
    for(int i = (array.length - 1 - 1) / 2;i > 0;i--) {
        adjustDown(array,i,array.length);
    }
}

public static void HeapSort(int[] array) {
    create(array);
    
    int len = array.length - 1;
    
    while(len > 0) {  //每次都将最一个元素与堆顶元素比较然后交换
        if(array[len] < array[0]) {
            int temp = array[0];
            array[0] = array[len];
            array[len] = temp;
            //交换之后向下调整
            adjustDown(array,0,len);
            len--;
        }
    }
}
7、归并排序

时间复杂度O(n*logn) 数据不敏感

空间复杂度O(n) 数据不敏感

归并排序也是分治法的思想,不断地将原数据分为两部分,直到不划分为止,开始对两部分元素进行排序合并。

 public static int[] MergeSort(int[] array) {
        if(array.length < 2) return array;
        int mid = array.length / 2;
     //分成左右两部分
        int[] left = Arrays.copyOfRange(array,0,mid);
        int[] right = Arrays.copyOfRange(array,mid,array.length);
     //对左右两部分进行递归合并
        return Merge(MergeSort(left),MergeSort(right));
    }

    public static int[] Merge(int[] left,int[] right) {
        int[] result = new int[left.length + right.length];
        for(int index = 0,i = 0,j = 0;index < result.length;index++) {
            if(i >= left.length) {  //左边走完,直接将右边的放入result
                result[index] = right[j++];
            }else if(j >= right.length) {  //右边走完,直接将左边的放入result
                result[index] = left[i++];
            }else if(left[i] > right[j]) {  //左右都没走完,比较然后放入result
                result[index] = right[j++];
            }else {
                result[index] = left[i++];
            }
        }
        return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值