0414-算法复盘 排序算法-冒泡排序、选择排序、插入排序、希尔排序、归并排序、堆排序、快速排序

1. 排序算法及时间复杂度分析

1.1 冒泡排序

思想:从无序队列的头部开始,进行两两比较,将最大的(最小的)元素放至队列的尾部

for(int i = 0; i < nums.length; i++){
    for(int j = 1; j < nums.length - i; j++){
		if(nums[j] > nums[j - 1]){
            int temp = nums[j];
            nums[j] = nums[j + 1];
            nums[j + 1] = temp;
        }
    }
}
//优化
boolean falg = true;
for(int i = 0;i < nums.length & flag; i++){
    flag = false;
    for(int j = 1; j < nums.length - i; j++){
		if(nums[j] > nums[j - 1]){
            int temp = nums[j];
            nums[j] = nums[j + 1];
            nums[j + 1] = temp;
            flag = true;
        }
    }
}

时间复杂度分析:需要n-1次循环,每次循环需要n - 1- i次比较,所以时间复杂度是O(n2)

稳定性分析:稳定的,当两个元素相等时,不进行两两交换

1.2 选择排序

思想:每一次都选择未排序的序列中的最大(最小)的元素放至没有排序的尾部

for(int i = 0;i < nums.length; i++){
    int minIndex = i;
    for(int j = i; j < nums.length; j++){
        if(nums[minIndex] > nums[j]){
            minIndex = j;
        }
    }
    int temp = nums[i];
    nums[i]  = nums[minIndex];
    nums[minIndex] = temp;
}

时间复杂度分析:两次for循环,最坏和最好的情况下每次循环都要进程n次,所以时间复杂度是0(n2)

稳定性:不稳定,因为每次选择的都是当前未排序序列最小的或者最大的

1.3 插入排序

思想:每次将一个元素,插入到已经排好序的正确位置,假设第一个元素已经有序

for(int i = 1;i < nums.length; i++){
    int temp = nums[i];
    int j;
    for(j = i - 1; j >= 0 && nums[j] > temp; j--){
        nums[j + 1] = nums[j];
    }
    nums[j + 1] = temp;
}

时间复杂度分析:两次for循环,一次for控制插入的元素,第二次for控制插入的位置,所以时间复杂福是O(n2)

稳定性分析:稳定

1.4 希尔排序

思想:建立在插入排序的思想上,将数组分为几个组,将每一组进行插入排序,最终只剩下一组

for(int gap = nums.length / 2 ; gap > 0; gap = gap / 2){
    for(int i = gap; i < nums.length; i++){
        int temp = nums[i];
        int j;
        for(j = i - gap; j >= 0 && temp < nums[j]; j -= gap){
            nums[j + gap] = nums[j];
        }
        nums[j + gap] = temp;
    }
}

时间复杂度:希尔排序的时间复杂度取决于增量gap的取值,如果gap为1那么希尔排序就退化为插入排序,时间复杂度为O(n2),而选择gap为2的话,时间复杂度为O(n1.5)

稳定性:如果gap的选取为1那么希尔排序变为插入排序,这就是一种稳定性的排序,但是如果gap不为1,那么是不稳定的,因为选取的分组不一样

1.5 归并排序

思想:归并排序是分治法的思想,因为如果一个数组只有一个元素,那么这个数组是有序的。归并排序就是将一个大数组切分为小数组,使得小数组只有一个元素,这是分的过程,而治只需要将两个有序之间的数组合并成一个有序的数组

public void sort(){
    int[] temp = new int[nums.length];
    mergeSort(nums, 0 ,nums.length - 1, temp);
}
public void mergeSort(int[] nums, int left, int right, int[] temp){
    if(left >= right)	return;
    int mid = (left + right) >> 1;
    mergeSort(nums, left, mid, temp);
    mergeSort(nums, mid + 1, right, temp);
    int i = left, j = mid + 1, count = 0;
    while(i <= mid || j <= right){
        if(j > right || (i <= mid && nums[i] < nums[j])){
            temp[count++] = nums[i++];
        }else{
			temp[count++] = nums[j++];
        }
    }
    for(int k = left; k < left + count;k++){
        nums[k] = temp[k - left];
    }
}

时间复杂度分析:一个长度为n的序列,要拆分为n个1的序列,那么总共有logn层,而对于每一层的合的操作都是n,所以时间复杂度是O(nlogn)

稳定性分析:稳定

1.6 堆排序

思想:维护一个大根堆(每一个节点的父节点都比子节点更大)或者小根堆(每一个节点的父节点都比子节点更小)然后让根节点与数组中的最后一个元素进行交换,直到所有元素都有序

public void sort(){

}
public void sortHeap(int[] nums){
    for(int i = nums.length / 2 - 1; i >= 0; i--){
        adjuetHeap(nums, nums.length, i);
    }
    for(int i = nums.length - 1; i >= 0; i--){
		int temp = nums[i];
        nums[i] = nums[0];
        nums[0] = temp;
        adjuetHeap(nums, i, 0);
    }
}
public void adjuetHeap(int[] nums, int length, int i){
    int temp = nums[i];
    for(int j = i * 2 + 1; j < length;j = j * 2 + 1){
        if(j + 1 < length && nums[j] < nums[j + 1]){
            j++;
        }
        if(nums[j] > temp){
            nums[i] = nums[j];
            i = j;
        }
    }
    nums[i] = temp;
}

时间复杂度分析:堆排序在初始化堆的过程的时间复杂度是O(n),而在排序重建堆的过程是因为有n个元素需要与最后一个元素进行交换,而交换完成之后又要重新建堆所以时间复杂度是O(nlogn),那么总的时间复杂度是O(nlogn)

稳定性分析,堆排序是不稳定的

1.7 快速排序

思想:每次排序选取一个基准数,然后找到这个基准数的合适位置,使得在这个位置之前的数都比这个基准数小(升序),比这个位置之前的数都比这个基准数大,然后分别对这个位置之前的数和这个位置之后的数进行快速排序

public void sort(){

}
public void quickSort(int[] nums, int left, int right){
	if(left > right) return;
    int b = nums[left], i = left, j = right;
    while(i != j){
        while(i < j && nums[j] >= b) j--;
        while(i < j && nums[i] <= b) i++;
        if(i < j){
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
    nums[left] = nums[i];
    nums[i] = b;
    quickSort(nums, left, i - 1);
    quickSort(nums, i + 1, right);
}

时间复杂度分析:平均时间复杂度是O(nlogn)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值