Java 冒泡排序,选择排序,插入排序,快速排序,归并排序

本文介绍了五种基本的排序算法:冒泡排序、选择排序、插入排序、快速排序和归并排序。详细阐述了每种排序算法的工作原理,包括它们的时间复杂度,并提供了相应的代码实现。通过对这些排序算法的理解,有助于提高编程能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

冒泡排序法

每次排序将最大的一个数字放到数组末尾,第二次排序将第二大的排到数组倒数第二个位置,如此重复,直到排完。

时间复杂度为O(n^2),因为经历了两个for循环。

第一层i的循环代表每个元素都要比较一轮。第二层j=0表示从每一轮都要第一个开始比。
j<a.length - 1 - i的原因是后面i个元素已经排好了,已经为最大的几个了,无需再比较。

public  static  void bubbleSort() {
        int a[] = {5,4,3,2,1};
        
        for (int i=0;i<a.length-1;i++){
            //i的循环代表每个元素都要比较一轮。j=0表示从每一轮都要第一个开始比
            //j<a.length - 1 - i的原因是后面i个元素已经排好了,已经为最大的几个了,无需再比较、
            for (int j=0;j<a.length - 1 - i;j++){
                if (a[j]>a[j+1]){
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
        //输出排序后的数组
        for (int y=0;y<a.length;y++){
            System.out.println(a[y]);
        }

    }

 

选择排序法

第一次排序时,找到最小的值,与第一个互换,使最小值在第一个位置,第二次排序,再找出除了第一个以外最小的值,与第二位互换,使第二小的数在第二的位置,如此循环。每次将剩余数组中最小值放置到剩余的最前面。

因为经历了两次循环,所以时间复杂度为O(n^2)。

代码如下

public static void selectionSort(){
        int a[] = {1,3,2,8,4,5,9,6,7};
        for (int i = 0;i<a.length;i++){
            //初始化最小值为当前i的值
            int flag = i;
            for (int j=i;j<a.length;j++){
                if (a[flag]>a[j]){
                    //记下目前找到的最小值所在的位置
                    flag = j;
                }
            }
            if (flag != i){
                //找到本轮循环的最小的数以后,将最小值与当前i位置进行交换
                int temp = a[i];
                a[i] = a[flag];
                a[flag] = temp;
            }
        }

        //输出排序后的数组
        for (int y=0;y<a.length;y++){
            System.out.println(a[y]);
        }
    }

 

插入排序

插入排序类似插扑克牌,每当摸到一直牌,都会把它插到我们已经排好的手牌中。插入排序就是先拿出第一个数来当手牌,然后再摸出第二个数在合适位置将其插入到手牌,再摸出第三个数在合适位置插入到手牌,以此类推。这样,手牌里的数一定都是排序好的,摸完所有数,就排序好整个数组了。

时间复杂度为O(n^2)。

代码如下:

public static void insertSort(){
        int a[] = {1,3,2,8,4,5,9,6,7};
        int insert;//要摸的也就是要插入的数
        int j;
        for (int i=1;i<a.length;i++){//拿出一个数当手牌,从数组的第二个元素开始循环将数组中的元素插入
            insert = a[i];
            j = i - 1;
            while (j >= 0 && insert < a[j]){// 如果要插入的牌小于第j个元素,就将第j个元素向后移动,给前面空出一个位置插牌
                a[j+1] = a[j];
                j--;
            }
            a[j+1] = insert;// 直到要插入的牌不小于第j个元素,将牌插入到j元素之后的j+1位置
        }
        //输出排序后的数组
        for (int y=0;y<a.length;y++){
            System.out.println(a[y]);
        }
    }

 

快速排序

 

快速排序的时间复杂度是O(nlogn)

快速排序用了分治的思想,什么是分治?

在计算机科学中,分治法是一种很重要的算法。分治算法,字面上的解释是“分而治之”,分治算法主要是三点:
1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----“分”
2.将最后子问题可以简单的直接求解----“治”

3.将所有子问题的解合并起来就是原问题打得解----“合”

快速排序算法需要先从数组中随便挑出一个基准值(一般是数组第一个数),目的就是让左边的数都小于基准值,右边的数都大于基准值。

1.首先定义两个变量 i 和 j ,分别指向序列最左边和最右边。声明一个临时变量存储基准值。从数组两端将数组两边数一次和基准值进行比较,找出左边的一个数大于基准值和右边的一个数小于基准值的,将这两个数互换。

2.如此重复,直到 i 和 j 重合,重合后将重合位置的数与基准值进行比较,将两者互换位置,然后分别对左半边和右半边的序列进行这样的排序,也就是用了分治的思想。左边右边分别选出基准值和 i , j 等两边都排好了整个数组也就排好了。

详细过程参考点击打开链接

快速排序不稳定,平均时间复杂度为nlog(n),当大数都集中在前半段,小数都在后半段,那么每次都要讲大数换到后半段,小数换到前半段,这样情况下时最差的时间复杂度n^2。

代码如下

public static void quickSort(int[]a,int begin,int end){
        if(begin>end){
            return;
        }
        int i,j;//数组的最左边和最右边
        int check;
        i = begin;
        j = end;
        check = a[begin];//临时变量存储基准值
        while (i<j){
            while (a[j] >= check && i < j){
                j--;
            }
            while (a[i] <= check && i < j){
                i++;
            }
            if (i < j){
                //将找到的两个数互换
                int temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }

        //将基准值与i,j重合位置的数互换
        a[begin] = a[i];
        a[i] = check;
        //分治,分别对左右两边序列进行快速排序
        quickSort(a,begin,j-1);
        quickSort(a,j+1,end);

        //输出排序后的数组
        for (int y=0;y<a.length;y++){
            System.out.println(a[y]);
        }
    }

 

归并排序

归并排序也是用了分治的思想,排序的过程分为两个阶段:

1.通过递归由上而下的将数组分成若干个左右子序列(每个子序列只有一个元素)

2.通过递归由下而上的将这些子序列通过插入合成为一个排好序的序列。

明确了这两步后就单独来看第一步和第二步:

第一步很简单,就是讲数组无限的对半拆解,直到只有一个元素。定义一个mid为begin和end和的二分之一,左子序列为begin到mid,右子序列为mid+1到end,这样递归下去。

第二步就是将两个子序列合并在一起成为一个排好序的序列。具体的步骤为:

两步明确了就可以代码实现了:

public class MergeSort {
    public static void main(String[] args) {
        int []arr = {9,8,7,6,5,4,3,2,1,10,11,15,12,19,17};
        int []temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));
    }
    //递归分治,将数组分成若干个左右子序列
    public static void mergeSort(int []arr,int begin,int end,int []temp){
        if (begin < end){
            int mid = (begin + end) / 2 ;
            mergeSort(arr,begin,mid,temp);//左边归并排序,使得左子序列有序
            mergeSort(arr,mid+1,end,temp);//右边归并排序,使得右子序列有序
            merge(arr,begin,mid,end,temp);
        }
    }
    //并,将两个已经排好序的左右子序列合并成一个序列
    public static void merge(int []arr,int begin,int mid,int end,int []temp){
        int i = begin;//左子序列的指针
        int j = mid + 1;//右子序列的指针
        int t = 0;//临时存放元素的数组的指针
        //从左边开始比较左右子序列的元素大小,谁小谁插入到临时数组中
        while (i <= mid && j <= end){
            if (arr[i] < arr[j]){
                temp[t++] = arr[i++];
            }else{
                temp[t++] = arr[j++];
            }
        }
        //如果左子序列还有剩余元素,插入到临时数组中
        while (i <= mid){
            temp[t++] = arr[i++];
        }
        //如果右子序列还有剩余元素,插入到临时数组中
        while (j <= end){
            temp[t++] = arr[j++];
        }
        //将临时数组存放的元素更新到原数组中
        t = 0;
        while (begin <= end){
            arr[begin++] = temp[t++];
        }
    }
}

结果:

 

归并排序比较稳定,时间复杂度为nlog(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值