交换排序的两种算法(Java代码实现)

目录

交换排序:

基本思想:

1:冒泡排序:

基本思想:

过程:

2:快速排序:

基本思想:

过程:


交换排序:

基本思想:

        两两比较待排序的数,一旦两个数不满足次序要求则进行交换,直到整个序列满足要求(及有序)为止。而交换排序大致为以下两种:1:冒泡排序.2:快速排序.

1:冒泡排序:

基本思想:

        冒泡排序是最简单的一种交换排序方法,它通过两两比较相邻的数,如果发生逆序,则两两交换,从而使得小数如气泡般向上逐渐“飘出”(左移),大数如石块一样向下逐渐“坠落”(右移)。

过程:

        先看一张演示图:

        不难看出,从第一个数开始进行两两比较交换,第一次可获得最大数,在数组最后一位,然后进行第二次两两比较,以此类推。

代码实现:

import java.util.Arrays;

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

    public static void Bubblesort(int[] s){
        int a=s.length-1;//记录需要比较的数组长度
        int flag=1;//判断是否发生交换,1为发生交换,2为未发生交换
        while(a>0&&flag==1){//未发生交换或者数组长度小于等于0,都说明了数组已经排序为有序数组
            flag=0;//先将flag设置为未交换
            for (int i=1;i<=a;i++) {
                if (s[i] < s[i - 1]) {//将大数往后移动
                    int temp = s[i];
                    s[i] = s[i - 1];
                    s[i - 1] = temp;
                    flag = 1;//发生交换,设置为1
                }
            }
            --a;//第一趟交换完成后,最大数已经排至最后,所以将需要交换排序的数组长度减一
        }
        System.out.println(Arrays.toString(s));//输出排好序的数组
    }

}

结果:

时间复杂度:O(n^{2})

空间复杂度:O(1)

算法特点:

        (1):稳定排序。

        (2):移动次数较多,当初始记录无序,n较大时,不宜采用。

2:快速排序:

基本思想:

        快速排序是由冒泡排序改进而来。快速排序方法中可以一次交换消除多个逆序,比冒泡排序一次交换只能消除一个逆序速度更快。

过程:

        上图:

        在快速排序中先选出一个关键字pivotkey(也就是一个数)然后以数组开头low和数组末尾high同时与关键字进行比较。

        low所指数大于关键字则停止移动,high所指数小于关键字则停止移动,交换low和high所指向的数,直到low=high,再将关键字与low与high汇合点所指向的数交换。

        这样完成第一次排序,关键字左边全是小于它的数,右边全是大于它的数。再对左子数组和右子数组进行相同排序(递归调用相同方法),直到排序完成(子表长度等于1)。

代码实现:

import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int[] a={2,6,3,8,1,4,2,7};
        Quicksort(a,0,a.length);//调用方法,第一次begin默认为0,第一次end默认为数组长度
        System.out.println(Arrays.toString(a));//输出排序完成的数组
    }

    public static void Quicksort(int[] s,int begin,int end) {
        end=end-1;//防止数组下标溢出
        if (begin<end) {//判断数组长度是否大于1
            int temp = s[begin];//取第一个数为初始关键字
            int i = begin;
            int j = end;
            while (i < j) {//循环直到i不小于j
                //必须先找j,先找i会排序失败,这样的优点是可以减少比较次数
                while (s[j] >= temp && j > i) {//循环直到找到小于关键字的数
                    j--;//end减一
                }
                while (s[i] <= temp && j > i) {//循环直到找到大于关键字的数
                    i++;//begin加一
                }
                if (j > i) {//判断end是否在begin后面,在则交换两个位置所含数字
                    int t = s[i];
                    s[i] = s[j];
                    s[j] = t;
                }
            }
            s[begin] = s[i];//将关键字与s[i]交换,这样关键字左边都是小于它的数,右边都是大于它的数(此时i=j)
            s[i] = temp;
            Quicksort(s, begin, i);//递归求左子数组(因为每次递归第一条语句会让end-1,所以使用i而不使用i-1)
            Quicksort(s, i + 1, end + 1);//递归求右子数组
        }
    }
    //另一种普通方法:
   public static void Quicksort1(int[] s,int begin,int end) {
        end=end-1;//防止数组下标溢出
        if (begin<end) {//判断数组长度是否大于1
            int temp = s[begin];//取第一个数为初始关键字
            int i = begin;
            int j = end;
            while (i<j) {//循环直到i不小于j
                //这一种方法先找i或先找j都可
                /*while (s[j] >= temp) {//循环直到找到小于关键字的数
                    j--;//end减一
                }*/
                while (s[i] <= temp) {//循环直到找到大于关键字的数
                    i++;//begin加一
                }
                while (s[j] >= temp) {//循环直到找到小于关键字的数
                    j--;//end减一
                }
                if (j > i) {//判断end是否在begin后面,在则交换两个位置所含数字
                    int t = s[i];
                    s[i] = s[j];
                    s[j] = t;
                }
            }
            s[begin] = s[j];//将关键字与s[i]交换,这样关键字左边都是小于它的数,右边都是大于它的数(这里i,j不一定相等)
            s[j] = temp;
            System.out.println(Arrays.toString(s));
            Quicksort(s, begin, j);//递归求左子数组
            Quicksort(s, j + 1, end + 1);//递归求右子数组
        }
    }


}

结果:

时间复杂度:O(nlog_{2}n)

空间复杂度:O(log_{2}n)

算法特点:

        (1):不稳定排序。

        (2):适合初始记录无序,n较大情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值