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

来源:互联网 发布:淘宝好评返现怎么做 编辑:程序博客网 时间:2024/04/30 16:48

用到的工具: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);                }            }        }    }}
1 0