【排序算法】多种排序算法演示

用到的工具:print、swap


/**print工具方法*/
private static void print(int[] a) {
    for(int i=0;i<a.length;i++){
        System.out.print(a[i]+" ");
    }
    System.out.println();
}

/**swap工具方法*/
private static void swap(int[] a, int i, int j) {
    int temp;
    temp=a[i];
    a[i]=a[j];
    a[j]=temp;
}

(一) 冒泡排序

这里写图片描述

算法描述:

(1). 设待排序记录序列中的记录个数为n。
(2). 一般地,第i趟起泡排序从0到n-i-1。
(3). 依次比较相邻两个记录的关键字,如果发生逆序,则交换之。
(4). 其结果是这n-i-1个记录中,关键字最大的记录被交换到第n-i-1的位置上,最多作n-1趟。

代码演示:

/**冒泡排序方法:*/
public static int[] BubbleSortMethod(int[] a){
    for(int i=0;i<a.length;i++){
    /**1.相邻的两个(a[j]、a[j+1])相互比较,j是从0到a.length-i-1*/
        for(int j=0;j<a.length-i-1;j++){
            if(a[j]>a[j+1]){
                swap(a, j, j+1);
            }
        }
    }
    return a;
}

(二)近似选择排序

这里写图片描述

代码描述:

(1).设待排序记录序列中的记录个数为n。
(2).一般地,第i趟起泡排序从 i+1到n。
(3).依次用第i个与[i+1,n]之间的数比较,将得到的最大的值放在n-1的位置,依次类推,直到i为n-1。

代码演示:

public static void ApproximateSelectionSort(int[] a){
    for(int i=0;i<a.length;i++){
    /**第i个与[i+1,a.length]之间的所有进行比较,得到一个最大的放到n-i的位置上。*/
        for(int j=i+1;j<a.length;j++){
            if(a[i]>a[j]){
                swap(a, i, j);
            }
        }
    }
    print(a);
}

(三)选择排序

这里写图片描述

算法描述

(1)首先通过n-1次比较,从n个数中找出最小的。
(2) 将它与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。
(3)再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换——第二趟选择排序。
(4)重复上述过程,共经过n-1趟排序后,排序结束。

代码演示:

public static void selectSort(int[] a){
    for(int i=0;i<a.length;i++){
        int temp=a[i];//取第i个数为最小值
        int k=i;//最小值的位置k为i
        for(int j=i;j<a.length;j++){
            if(temp>a[j]){//如果第j个数比最小值还要小,进行交换
                temp=a[j];
                k=j;
            }
        }
        swap(a,i,k);
    }
    print(a);
}

(四)直接插入排序

这里写图片描述

算法描述:

记录存放在数组R[0….n-1]中,排序过程的某一中间时刻,R被划分成两个子区间R[0…i-1]和R[i….n-1],其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。

基本操作:

将当前无序区的第1个记录R[i]插入到有序区R[0….i-1]中适当的位置,使R[0…i]变为新的有序区。

操作细节:

当插入第i(i≥1)个对象时, 前面的r[0], r[1], …, r[i-1]已经排好序。
用r[i]的关键字与r[i-1], r[i-2], …的关键字顺序进行比较(和顺序查找类似),如果小于,则将r[x]向后移动(插入位置后的记录向后顺移);找到插入位置即将r[i]插入。

代码演示:

public static void Straight_Insertion_Sort(int[] a){
    for(int i=0;i<a.length-1;i++){
        int temp=a[i+1];//临时需要插入的值
        while(temp<a[i]){//循环条件:当需要插入的值比其前边的值小的时候,进行向右移动数值
                a[i+1]=a[i];
                i--;//从右向左依次遍历每个数
                if(i<0){
                    break;
                }
            }
            a[i+1]=temp;//最后将temp插入到空出来的位置上,i+1是因为i--最后多减了一次1,所以此处要加上1
        }
    print(a);
}

(五)二分法插入排序

算法描述:

◆在直接插入排序的基础上,利用二分(折半)查找算法决策出当前元素所要插入的位置。

二分查找:找到中间元素,如果中间元素比当前元素大,则当前元素要插入到中间元素的左侧;否则,中间元素比当前元素小,则当前元素要插入到中间元素的右侧。

◆找到当前元素的插入位置i之后,把i和high之间的元素从后往前依次后移一个位置,然后再把当前元素放入位置i。

代码演示:

/**
*  high为何要-1? low为何要+1?
* (1)Java中有个规范:左闭右开[ low , high )。
* (2)经过二分法得到了mid,分为两个区间:[low,mid) 、[mid, high)。
* (3)可以看出:(temp<=a[mid])? high=mid-1:low=mid+1;
*/

public static void dichotomy(int[] a){
    for(int i=0;i<a.length-1;i++){
        int temp=a[i+1];
        int low=0;
        int high=i;
        while(low<=high){ //循环条件:当low<=high时候进行比较取值
            int mid=(low+high)/2;
            if(temp<=a[mid]){ //确定下一次high、low的值
                high=mid-1;
            }else{
                low=mid+1;
            }
        }
        int j=high; //确定需要下次替换的位置
        for(int k=i;k>j;k--){ //[i , high]之间的所有数右移
            a[k+1]=a[k];
        }
        a[j+1]=temp;
    }
    print(a);
}

(六)希尔排序

希尔排序又称缩小增量排序,是1959年由D.L.Shell提出来的。

算法描述:

(1)先取定一个小于n的整数gap1作为第一个增量,把整个序列分成gap1组。所有距离为gap1的倍数的元素放在同一组中,在各组内分别进行排序(分组内采用直接插入排序或其它基本方式的排序)。

(2)然后取第二个增量gap2<gap1,重复上述的分组和排序。

(3)依此类推,直至增量gap=1,即所有元素放在同一组中进行排序为止。

算法分析:

(1)开始时 gap 的值较大, 子序列中的元素较少, 排序速度较快。

(2)随着排序进展, gap 值逐渐变小, 子序列中元素个数逐渐变多,由于前面大多数元素已基本有序, 所以排序速度仍然很快。

(3)分组后n值减小,n²更小,而T(n)=O(n²),所以T(n)从总体上看是减小了。

(4)Gap的取法有多种。 shell 提出取 gap = n/2 ,gap = gap/2 ,…,直到gap = 1。gap若是奇,则gap=gap+1

代码演示:

public static void shellSort(int[] a){
    for(int gap=(a.length+1)/2;gap>0;gap/=2){
        for(int i=0;i<a.length-gap;i++){
            for(int j=i;j<a.length-gap;j+=gap){
                if(a[j]>a[j+gap]){
                    swap(a,j,j+gap);
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值