java 排序算法整理の堆排序,归并排序

来源:互联网 发布:install brew on mac 编辑:程序博客网 时间:2024/05/21 09:20

八种排序算法,各有各的运行机制,注意事项今天主要讲,堆排序以及归并排序,以及总结一下其他排序算法......当然这里都是我会的,基数排序还没有去研究

第一基础类排序

冒泡排序,选择排序,插入排序

之所以说是基础排序,是因为这类排序不需要费多大思想去想他们,只需要根据排序的基本思想就能实现。(当然这只是我个人的理解)

冒泡排序:故名思义该算法很像水泡,将一个个大数(小数)沉到数组的低端或者反过来上升到数组的首位,实现须知,第二层循环从0开始但是截至位是数组长度减去第一层循环

的循环下标即  int j  =0 ; j<length-1-i;j++;之所以要length-1是因为每一次比较的是a[j]与a[j+1]的大小,这是为了避免溢出。至于可以加标志位放于交换体里,若第二层循环没有发生交换位置那么说明数组已经有序了,所以该算法比较适合局部有一点混乱的数据

选择排序:和冒泡排序有点像,也可以利用两个for循环就能解决,每一次外层循环开始前,利用临时变量temp去吧首位的a[i]的数据记录为最小,再用k  = i;记录最小值位置,然后进入内层循环,此时内层循环就需要从j=i+1循环起走,因为我们已经假设了当前一号位最小然后比较 a[j]与temp的大小,若是a[j]>temp 那么就把temp=a[j];k = j;知道内层循环结束,最后将a[k]=a[i];a[i]=temp;最小值往前换.......

插入排序:插入排序像选择排序一样也会利用一个中间变量,不过这个中间变量变成了数组的首位a[0],外层循环从第三位开始for(int i =2;i<length;i++)因为,第一位是哨兵位用于每次存放临时变量,每一次外层循环开始时就判定是不是a[j]<a[j-1]成立则进入循环进行插入排序,反之不执行,先把a[0] = a[j]; a[j] = a[j-1]; 定义pos = 1;开始第二次循环,当然现在的循环要从i-2开始因为,我们已经将那两个数据操作了,然后把a[0]位的数据和后面未比较的有序数据进行比较,若是依然小于,则后面的数据一次后移,反之则直接将插入位置定位在pos = k+1;break;  出去之后然后a[pos] = a[0];a[0] = 0;继续外层循环。

第二类进阶排序

堆排序:所谓堆排序就是将数组建成一个堆,然后通过每次取堆的首位数据,进行排序。这里所谓的堆就是一棵二叉树,父节点的数据大于(或小于)两个左右孩子的数据,建队需要对n/2  -1 其中n是节点数就是数组的长度,这个表达式得到的是最后一个父节点的数组位置,然后向后循环,到0,把所有父节点遍历了,进行数据整理形成一个堆;形成堆过后将树根处a[0]与最后一个元素交换,然后整理交换过后的数组,让他变成一个堆...这样一直调用整理方法。所以堆排序我们有几个函数下面是  每个函数的代码

public static void dui_Sort(int[] a){ //排序   进行每一次交换,然后整理
int l = a.length;
for (int i = l-1; i >= 1; i--) {
fun_Swap(a,0,i);
fun_RenewDui(a,0,i);
}
}
public static void set_zuixiaoDui(int[] a,int n){  //首先进行的就是建立最大堆
int j = n/2 -1;
for (int i = j; i >= 0; i--) {
fun_RenewDui(a,i,n);
}
}

    private static void fun_RenewDui(int[] a ,int i,int n){ //整理函数,确保处在父节点的数是最小的,遍历完整个堆
    int j = 2*i+1;
    int temp = a[i];
    while(j<n){
    if(j+1 < n && a[j+1]>=a[j])
    j++;
   
    if(a[j] <= temp)
    break;
   
    a[i]=a[j];
    i = j;
    j=2*i+1;
    }
    a[i] = temp;
    }
    public static void fun_Swap(int[] a,int i,int j){//交换函数
    int temp ;
    temp = a[i];
    a[i] = a[j];
    a[j] = temp;
    }

希尔排序:官方名称就是减小增量的插入排序。你先观察目测出待排数组的长度,然后你分出步长来对他进行排序,比如步长int[] nec = {4,2,1}则是进行了三次插入排序,首先进行步长是4的插入,接着是2最后是1,这样的话对于的很多数据的话,效率高一些,到步长是1的时候很多都是有序的,可以节省很多循环时间,这是源自于插入排序原理来说的。

第三类递归排序

快速排序

快速排序,就是利用递归,不断把数组化分成,以第一个元素作为基准点,右边的元素都是大于这个基准点,左边的都是小于,不断的递归调用..就可以排好序,之前的文章谢过了,就不多说了。

归并排序

归并排序和快速排序的递归原理一样,同样都是递归调用(只是调用时候返回的时机不一样),不过归并排序的整理方法里面需要的是一个临时数组作为中介。当然代码是我研究了网上高手的代码,整理了一下..

public static void sort_Guibing(int[] num,int low,int high){
int mid = low + (high-low)/2;
if(low<high){
sort_Guibing(num,low,mid);
sort_Guibing(num,mid+1,high);
merge(num,low,mid,high);
}
}


public static void merge(int[] num,int low,int mid,int high){
int[] temp = new int[high-low+1];
int l = low;
int h = mid+1;
int k = 0;

while(l<=mid && h<=high){
if(num[l]<num[h]){
temp[k++] = num[l++]; 
}else{
temp[k++] = num[h++];
}
}

while(l<=mid){
temp[k++] = num[l++];
}

while(h<=high){
temp[k++] = num[h++];
}

for (int i = 0; i < temp.length; i++) {
num[i+low] = temp[i];
}

}

0 0
原创粉丝点击