排序算法

在这里插入图片描述

1 选择排序SelectionSort

最简单,也有优化空间

如何计算时间和空间复杂度
算法的验证 随机数据生成器 对数器
写算法程序的哲学

思想:就是先找到最小的放到第一个(第一个原本的和最小的互换),在找第二小的

for(int i=0:i<arr.length-1;i++){
int minpos=i;//假设当前第一个就是最小的
for(int j=i+1;j<arr.length;j++){
if(arr[j]<arr[minpos])
minpos=j;//取出最小的那个数的位置,找出了下来进行交换
}//这里可能小伙伴们会疑惑为什么不直接交换数据,反而先找索引了。
因为假如是从第一个数开始的,他需要从前往后一直比较。如果碰到一个比它小的就交换值 ,太麻烦了 。时间上没有交换索引块。
if(minpos!=i)
int temp=arr[i];
arr[i]=arr[minpos];
arr[minpos]=temp;
}

冒泡排序移动数据有3条赋值语句,而选择排序的交换位置的只有1条赋值语句,因此在有序度相同的情况下,冒泡排序时间复杂度是选择排序的3倍,所以,选择排序性能更好
(原因就在与进行位置索引,交换,简单)
选择排序,可以优化 ,后面的一次循环,可以找到一个最小值,同时找到一个最大值,最小值放前面,最大值放后面
https://www.bilibili.com/video/BV14i4y1T7Af?p=7
后续:1 独立完成代码编写 2如何验证
3思考还有没有优化的空间
4写一个程序证明选择排序不稳定

2 冒泡排序 BubbleSort

public class BubbleSort {

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

    public static void main(String[] args) {
        int [] a = new int [] {9, 5, 1, 2, 7, 3, 4, 8, 6};

        BubbleSort.bubbleSort(a);
        // 打印展示排序结果
        Arrays.stream(a).forEach(System.out::println);
    }
}

思路:升序就是每一循环结束,把最大的放最后(它是相邻的相互交换)
作业:独立完成冒泡排序并验证,并修改算法,使其最好复杂度为0(n)
最好的情况下时间复杂度两个for循环是n的平方,为什么结论是n,如何进行优化得到n,好像可以优化进行提前结束。

3 插入排序(InsertionSort)

对于基本有序的数组最好用
稳定

1.冒泡排序和插入排序的时间复杂度都是 O(n^2),都是原地排序算法(就是排序过程中不申请过多的存储空间,只利用原来存储的待排数据的存储空间进行比较和交换),为什么插入排序要比冒泡排序更受欢迎呢?

public class InsertionSort {
  public static void sort(int [] arrs){
        // 1、循环购买玩具:模拟玩具的增加过程
        for (int i = 0; i < arrs.length; i++) { // 从左到右 --> 循环
            // 2、对自己已有的玩具进行排序
//            for(int j = 0; j < i; j++) { // 和循环同向-数据比较:部分数据位置错乱!-数据交换位置   
            for(int j = i-1; j >= 0; j--) { // 数据比较--> 从右往左
                // 3、对玩具进行喜爱程度(数字大小)排序:交换数据--> 正确的结果
                if (arrs[j] > arrs[j+1]) {
                    // 交换数据/玩具
                    int temp = arrs[j];
                    arrs[j] = arrs[j+1];
                    arrs[j+1] = temp;
                }
            }
        }
    }
    public static void main(String[] args) {
        int [] a = new int [] {10, 8, 100, 78, 66, 33, 88};
       InsertionSort.sort(a);
     Arrays.stream(a).forEach(System.out::println);
    }
}

4 快速排序(QuickSort)

算法的思想:采用分治法(将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。)

求解:从整个数组中随机挑选一个元素作为基准,数组中小于基准的元素全部移到左边,大于的移到右边,即以该基准作为分界点。接着便可以按照此思想,递归的处理左边部分数组和右边部分数组。

import java.util.Arrays;

/**
 * 排序方式:快速排序的操作方式较高
 *      空间复杂度O(log n) 时间复杂度(n log n)
 */
public class QuickSort {

    public static void sort(int [] a, int left, int right) {
        // 设置排序结束的条件
        if( left > right ){
            return;
        }
        // 记录左边编号、记录右边编号
        int i = left, j = right;
        // 记录基准数字
        int base = a[left];

        // 核心算法
        while (i != j){
            // 右侧编号查找数字
            while(j > i && a[j] >= base) {
                j--;
            } 
            // 左侧编号查找数字
            while(i < j && a[i] <= base) {
                i++;
            }
            // 数字交换
            if(i < j) { 
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
        // 基准数字 和 i位置数字的交换
        a[left] = a[i];
        a[i] = base;
     
        // i位置是基准数字,不再参与排序过程
        // 左侧数字进行二次分类
        sort(a, left, i - 1);
        // 右侧数字进行二次分类
        sort(a, i + 1, right);
    }
//这个是方法的重载 ,参数和上面那个不一样。
    public static void sort(int [] a){
        sort(a, 0, a.length-1);
    }

    public static void main(String[] args) {
        int [] a = {5,2,12,6,67,3,2,3,6,5,23,243,32,567,67,878,3,34,6,6,345,23,21,3,45,100,45,23,2,3,45};
        QuickSort.sort(a);
        System.out.println(Arrays.toString(a));
    }
}
```其空间复杂度为log n,时间复杂度为nlog n

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值