数组(2)排序

本文深入探讨了四种经典的排序算法:插入排序、希尔排序、快速排序和归并排序。通过详细步骤和实例展示了它们的工作原理,包括减少交换次数的插入排序改进、分组插入的希尔排序、递归分治的快速排序以及利用二叉树特性的堆排序。这些排序算法在不同场景下有着各自的优势,对于理解算法思想和提升编程能力具有重要意义。
摘要由CSDN通过智能技术生成

1、插入排序-改进

        插入排序每次和前边的比较时,如果小于前边就会每次都交换。可是设置一个变量获取第n个数字,然后进行比较,如果逆序则让n-1的下标+1;直至不满足条件时,再将获取的变量赋给对应的位置,这样可以减少交换的次数,代码如下。

        int[]  a= {3,4,2,5,1};

        int j,t;

        for(int i=1 ; i < a.length ; i++){//从第二个下标开始,共循环length-1次

                t=a[i];//获取第i个值

                for( j = i ; j > 0 ; j - - ){//与前边的值进行比较,逆序则将前一个位置向后移动一次

                        if(t<a[j-1]){                                a[j]=a[j-1];                        }

                        else{                                break;                        }//不满足则返回。

                }a[j]=t;//根据获取到的实际位置将值放进去

        }

2、希尔排序

        希尔排序是插入排序的缩小增量排序,可以理解为分组插入排序。这个排序的代码还是比较上头的。大致的排序方式我用表格的形式表现。

362178045
362178045
360158247
360158247
012436587
012345678

        比如0-8,9个数字组成的数组,先分两组,排序。再多分两组,再排序。以此类推

        int[]  a = {3,6,2,1,7,8,0,4,5};

        for( int i = a.length/2 ; i > 0 ; i / = 2){//每次对半分组,只至分为一组。

                for( int j = i ; j < a.length ; j + + ){//插入排序,从每组的第二个下标开始

                        for(int k = j ; k>= i; k -= i){//从每组的第二个数字开始,每次递减步长,直至第二个数字

                                if( a[k]<a[k-i] )  { int t=a[k];  a[k]=a[k-i]; a[k-i]=t;}  //逆序则交换

                        }

                }

        }

3、快速排序

        去一个数组中的关建值(可以理解为中值),将数组中小于关建值的放在左边,大于关键值的放在右边,使用递归循环直至循环范围只有一个数。

362178045
06
13
102378645
014578
012345678

        quicksort(int[ ]  a , int left , int right){

                int i , j , t , temp;

                while( left > right){return ;}//确认循环范围不满足条件返回

                i = left ; j = right ; temp = a[left] ; 

                while( i != j){//当左下标等于右下标时,当前循环结束

                        while( a[j] > temp && i < j){//当最右边的数字大于关建值时需要左移下标。

                                j --;

                        }

                        while( a[i] <= temp && i<j){//当最左边的值小于等于关建值需要右移下标。

                                i++;

                        }

                        if( a[i] > a[j]){//当左边大于关键值,右边小于时,且左边关建值大于右边,互换位置。

                                t=a[i]; a[i]=a[j]; a[j]=t; 

                        }

                }//循环执行内容,直至两个下标相等为止。

                a[left]=a[i];//当循环结束,i为中间值对应的为止,与起始为止交换

                a[i]=temp;

                quicksort(a,left,i-1);//递归调用当前循环

                quicksort(a,i+1,right);

        }

4、归并排序

        使用递归,将数组拆分两个小组,直至数组只有一个值。依次取两个数组中最小的数字合并,当一个数组为空后,另一数组直接全部取出。

54823716
54823716
45283716
24481367
12345678

public static void mergeSort(int[] a, int first , int end ,int[] temp){

        if(first<nd){//只要数组的长度大于1,就能继续分组直至1

                int mid=(first+end)/2;

                mergeSort(int[] a, first , mid , temp);//递归分组,每次分组后排序

                mergeSort(int[] a, mid+1, end ,temp);

                mergeArray(int[] a,first , mid ,end , temp);//合并排序

        }

}

public static void mergeArray(int[] a, int first ,int mid , int end , int temp){

        int i=first;int m=mid;//第一组       int j=mid+1;int n=end;//第二组        int k=0;//操作temp下标

        while(i <= m && j <= n){//当某一组的值取完

                if(a[i] <= a[j]){//判断两个序列的对应值,按顺序放入temp数组。

                        temp[k]=a[i];        i++;        k++;//放入后自增

                }else{

                        temp[k]=a[j];        j++;        k++;//放入后自增

                }

        }

        while(i<=m){//如果j序列取完后直接将i序列全部放入

                temp[k]=a[i];        i++;        k++;

        }        

        while(j <= n){//如果i序列取完后直接将j序列全部放入

                temp[k]=a[j];        j++;        k++;

        }

        for(int s=0 ; s<k ; s++){//将temp的值赋给a

                a[first+s]=temp[k];//temp数组一直是0开始赋值,a数组需要将起点设置到指定位置。

        }

}

5、堆排序

        利用堆(二叉树)结构进行排序,子节点的值总是小于父节点的值。

public static void main(String args[]){
    int[] a={4,5,3,7,6,8,1};
    heapSort(a);
    System.out.print(Arrays.toString(a));
}
public static void heapSort(int[] arr){
    for(int i=arr.length/2-1;i>=0;i--){//第一遍将整个树排序
        adjustHeap(arr,i,arr.length);
    }
    for(int j=arr.length-1;j>0;j--){
        swap(arr,0,j);//将第一个和未排序的最后一个交换位置
        adjustHeap(arr,0,j);//交换排序
    }
}
public static void swap(int[] arr,int a,int b){//交换方法
    int temp=arr[a];
    arr[a]=arr[b];
    arr[b]=temp;
}
public static void adjustHeap(int[] arr,int i,int len){
    int temp=arr[i];
    for(int k=i*2+1;k<len;k=k*2+1){//根据2*节点下标+1,获取子节点
        if(k+1<len&&arr[k]<arr[k+1]){//将两个子节点大的下标赋给k
            k++;
        }
        if(temp<arr[k]){//如果子节点较大的比节点大则交换
            arr[i]=arr[k];
            i=k;
        }else{//否则返回
            break;
        }
    }
    arr[i]=temp;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值