常用的排序算法-java

冒泡排序: 时间复杂度o(n^2)

原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,这样一趟过去后,最大或最小的数字被交换到了最后一位,然后再从头开始进行两两比较交换,直到倒数第二位时结束

public void  sort(int [] a){

  for(int i =0;i < a.length;i++ ){
      for(int j =1;i< a.length-1;j++){
          if(a[j]< a[j-1]){
         //相邻两个元素的遍历,每次只能得到一个最小值或者最大值
              swap(a[j] , a[j-1]);
          }
      }
  }
 }

选择排序 o(n^2)

第1趟,在待排序记录r[1]~~r[n]中选出最小的记录,将它与r[1]交换;第2趟,在待排序记录r[2]~r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕。

void sort(int [] a){
    for(int i =0;i < a.length ; i++){
        int min =i;//
        for (int j =i+1; j < a.length ;j++){
            if(a [j] > a[min]){ 
            //一次遍历得到最小值的坐标。和之前的最小值交换
                min =j;
            }                
        }
        swap(a[i], a[min]);
    }
}

插入排序 o(n^2)

给定序列,存在一个分界线,分界线左边默认有序,右边默认无序(初始时默认第一个元素有序),每次取右边无序的第一个元素和左边有序的比较,并插入到左边合适的位置,分界线右移一位。

public void sort( int [] a){
    int j =0; 
    for (int i =1 ;i < a.length ; i++){
    //默认a[i] 之前为有序序列
        if(a[i] <a[i-1]){
            int  temp =a[i];
           //把 a[i] 插入到a[i-1]之前有序序列的合适位置上去-->
            for( j=i-1;j >0&& a[j]>temp ;j--){
                a[j+1] =a[j];
            }
            a[j+1] =temp;
        } 

    }

}

希尔排序

定义一个增量,把序列按增量分组,对每组使用直接插入排序算法排序,然后增量递归的进行递减;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

public void sort(int [] a){
    int j =0,split =a.length;
    //split 为定义的增量,每次排序完成后split/2 直至split 为0时排序结束
    while(split>0){
        split =split/2;

        for( int i =split ;i <a.length ;i++){
            if(a[i] <a[i -split]){
                int temp =a[i];
                for( j =i-split ; j>0&& a[j]>temp ;j=j-split){
                    a[j+split] =a[j];

                }
                a[j+split] =temp;        

            }
        }
    }
}

堆排序 o(nlog^n)

堆排序利用的数据结构是完全二叉树,对于一颗完全二叉树 ,他的任意一个节点i的左右子节点是 2*i+1 2*i+2(如果节点存在的话) 堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值。
基本思路是,构建一个完全二叉树,把他变成大根堆,然后每次把根节点(即最大值)移除,用最后的节点替代,这时数组长度减一继续构建大根堆。

public void sort( int [] a){
    //最后一个节点的坐标是 a[a.length/2-1],一次添加构建大根堆
    for( int j =a.length/2-1 ;j>0 ;j--){//先把数组构建成大根堆
        makeMax(a,j,a,length)
    }

    for (int i =a.length-1 ;i > 1;i--){
         swap(a[i],a[0]); //把大根堆的最大元素取出,放在数组末尾
        makeMax(a,0 ,i); //重新构建大根堆
    }
}
//构建大根堆,从根节点遍历,如果左右子叶大于根节点,则交换。
//
publci void makeMax(int [] a ,int start,int end){
    int temp=a[start]; //根节点
    int j =2*start+1;  //左子叶
    while(j< end){
        if(j+1 < end && a[j]< a[j+1]){ //找到左右子叶中比较大的
            j++;
        }
        if(temp > a[j]){
            break;  //当前节点大于左右子叶,跳出
        }

        a[start] =a[j];
        start =j;  //节点和子叶均指向交换后的下一个节点和子叶
        j=2*j+1; 
    }

    a[start] =temp;
}

归并排序 o(nlog^n)

将数组分成二组,如果这两组,如果这两组组内的数据都是有许多,那么就可以很方便的将这二组排序。如果这二组无序,就将这二组继续分成两组排序,当组里只有一个元素时是有序的,可以和相邻的元素合并

public void sort(int [] a ){
    int temp=new int[a.length];
    mergesort(a,0,a.length,temp);
}
public void mergesort(int [] a,int start ,int end ,int []temp){
    if(end >start){
        int  middle =(end-start)/2;
        mergesort(a,start,middle,temp);
        mergesort(a,middle,end,temp);
        mergearray(a,start,middle,end,temp);
    }
}

public void metgearray(int [] a,int start,int middle,int end,int temp){
    int i=j=k=l;
    whle(i < start &&j< end){
        if(a[j]>a[i]){
            temp[k++]=a[j++];
        }else{
            temp[k++]=a[i++];
        }
    }
    if(i< start ){
        temp[k++]=a[i++];
    }
    if(j< end){
        temp [k++]=a[k++];
    }

    for (i =0;i< k;i++){
        a[start+i]=temp[i];
    }
}

快速排序 o(nlog^n -n^2)

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

public void sort(int []a){
    mergesort(a,0,a.length);
}
public void mergesort(int [] a ,int start ,int end){
    while(start <end){
    //得到中间数,数组左边的数比他小,右边的比他大
        int middle =mergearray(a,start,end);
        mergesort(a,start,middle);
        mergesort(a,middle,end);
    }
}
public void mergearray(int [] a,int start ,int end){
    int mid=a[start];  //默认第一个  
    int i=stat;j=end;
    while(i<j){
        while (i<j&&a(j)>mid){
        //从后向前遍历,找到第一个小于mid的元素,放在i处
            j--;
        }
        if(j>i){
            a[i]=a[j];
            i++;
        }

        while(i<j&&a(i)<mid){
        //从前向后遍历,找到第一个大于mid的元素,放在j处
            i++;
        }
         if(j>i){
            a[j]=a[i];
            j--;
        }
    }
    a[i]=temp; //此时 i=j
    return i;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值