算法学习--排序

简单排序的方法:


(一)冒泡排序


若需要把队列从左往右依次从小到大排列,那么可以先比较第0号和第1号,若0号更大,则交换1号和0号的位置,再比较1号和2号的大小,以此类图,直到将最大的排到队末。之后进行第二轮的排序,步骤和第一轮一样,只是这轮比较到倒数第二个位置即可。反复执行此操作,最终可排除序列。


这样,算法做了约N*N/2次比较,而交换的次数少于比较的次数,大约为它的一半,即为N*N/4.


冒泡排序的核心算法如下:
public void bubble()
{
int out,in;


 for(out=max-1;out>1;out--)
  for(in=0;in<out;in++)
   if(a[in]>a[in+1])
     swap{in,in+1};
}





(二)选择排序


选择排序是把所有的数先全部扫一遍,从中挑出最小的数。最小的数和最左端的数交换位置,即到0号位置。这样最左端是有序的了,不需要交换。在这个算法中有序的是左端,而在冒泡算法中有序的是右端。之后,在扫描依次队伍,这次从1号位置开始,依次类似执行。


选择排序和冒泡排序执行了相同的次数N*(N-1)/2次,他们一样运行了O(N*N)的时间,但是选择排序更快,因为它进行的交换更少。


下面是选择排序的核心算法:

</pre><pre name="code" class="java">public void sort(){


int out,in;


for(out=0;out<max-1;out++)
  {
   min=out;
   for(in=out+1;in<max;in++)
    if(a[in]<a[min])
      min=in;
   swap(out,min);
}
}








(三)插入排序


若已经排好了一半,把未排的第一个数和已经排到额数相互比较,找到合适的位置,而这个未排的第一个数被称为“被标记的数”;
复制的次数大致等于比价的次数。然而,依次复制和依次比较的次数耗费时间不同,所以相对于随机数据,这个算法比冒泡排序块一倍,比选择排序略快。


核心算法如下:

public void insertsort(){
int in,out;
for(out=1;out<max;out++)
{
long temp=a[out];
in=out;
while(in>0&&a[in-1]>=temp)
{
a[in]=a[in-1];
--in;
}
a[in]=temp;
}
}



(四)希尔排序

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

各种基于实验的评估,估计它的时间级为O(N2/3)到O(N7/6)

packagecom.sort;
//不稳定
publicclass 希尔排序 {
     
    publicstatic void main(String[] args) {
        int[] a={49,38,65,97,76,13,27,49,78,34,12,64,1};
        System.out.println("排序之前:");
        for(inti = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
        //希尔排序
        intd = a.length;
        while(true){
            d = d / 2;
            for(intx=0;x<d;x++){
                for(inti=x+d;i<a.length;i=i+d){
                    inttemp = a[i];
                    intj;
                    for(j=i-d;j>=0&&a[j]>temp;j=j-d){
                        a[j+d] = a[j];
                    }
                    a[j+d] = temp;
                }
            }
            if(d == 1){
                break;
            }
        }
        System.out.println();
        System.out.println("排序之后:");
        for(inti = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");
        }
    }
}


(五)快速排序

要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

快速排序在大多数时候它是最快的,执行时间为O(N*logN)


publicstaticvoidquickSort(inta[],intstart,intend)
{inti,j;
i=start;
j=end;
if((a==null)||(a.length==0))
return;
while(i<j){
while(i<j&&a[i]<=a[j]){//以数组start下标的数据为key,右侧扫描
j--;
}
if(i<j){//右侧扫描,找出第一个比key小的,交换位置
inttemp=a[i];
a[i]=a[j];
a[j]=temp;
}
while(i<j&&a[i]<a[j]){//左侧扫描(此时a[j]中存储着key值)
i++;
}
if(i<j){//找出第一个比key大的,交换位置
inttemp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
if(i-start>1){
//递归调用,把key前面的完成排序
quickSort(a,start,i-1);
}
if(end-i>1){
quickSort(a,i+1,end);//递归调用,把key后面的完成排序
}
}
 
方式二
更有效率点的代码:
public<TextendsComparable<?superT>>T[]quickSort(T[]targetArr,
intstart,intend){
inti=start+1,j=end;
Tkey=targetArr[start];
SortUtil<T>sUtil=newSortUtil<T>();
 
if(start>=end){
returntargetArr;
}
 
/*从i++和j--两个方向搜索不满足条件的值并交换*
*条件为:i++方向小于key,j--方向大于key*/
while(true){
while(targetArr[j].compareTo(key)>0){
j--;
}
while(targetArr[i].compareTo(key)<0&&i<j){
i++;
}
if(i>=j){
break;
}
sUtil.swap(targetArr,i,j);
if(targetArr[i]==key){
j--;
}else{
i++;
}
}
 
/*关键数据放到‘中间’*/
sUtil.swap(targetArr,start,j);
 
if(start<i-1){
this.quickSort(targetArr,start,i-1);
}
if(j+1<end){
this.quickSort(targetArr,j+1,end);
}
 
returntargetArr;
}
 
方式三:减少交换次数,提高效率/
private<TextendsComparable<?superT>>voidquickSort(T[]targetArr,
intstart,intend){
inti=start,j=end;
Tkey=targetArr[start];
 
while(i<j){
//按j--方向遍历目标数组,直到比key小的值为止
while(j>i&&targetArr[j].compareTo(key)>=0){
j--;
}
if(i<j){
//targetArr[i]已经保存在key中,可将后面的数填入
targetArr[i]=targetArr[j];
}
//按i++方向遍历目标数组,直到比key大的值为止
while(i<j&&targetArr[i].compareTo(key)<0){
i++;
}
if(i<j){
//targetArr[j]已保存在targetArr[i]中,可将前面的值填入
targetArr[j]=targetArr[i];
}
}
//此时i==j
targetArr[i]=key;
 
if(i-start>1){
//递归调用,把key前面的完成排序
this.quickSort(targetArr,start,i-1);
}
if(end-j>1){
//递归调用,把key后面的完成排序
this.quickSort(targetArr,j+1,end);
}
}

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值