尚硅谷JAVA数据结构与算法--希尔排序

一、希尔排序

也称缩小增量排序,分为交换法和移动法,移动法速度更快。
在这里插入图片描述
交换法:

package 希尔排序;
//交换法
import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr={7,1,4,6,8,9,5,2,3,10};
        shellsort(arr);
    }

    public static void shellsort(int[] arr){
        int temp=0;
        int count=0;
        for(int gap=arr.length/2;gap>0;gap=gap/2){
            for (int i = gap; i < arr.length; i++) {
                for(int j=i-gap;j>=0;j-=gap){
                   if(arr[j]>arr[j+gap]){
                       temp=arr[j];
                       arr[j]=arr[j+gap];
                       arr[j+gap]=temp;
                   }
                }
            }
            System.out.println("希尔排序第"+(++count)+"轮结果="+ Arrays.toString(arr));
        }
    }
}

移动法(速度更快)

package 希尔排序;
//移动法(相比于交换法更快)
import java.util.Arrays;

public class ShellSort2 {
    public static void main(String[] args) {
        int[] arr={7,1,4,6,8,9,5,2,3,10};
        shellsort(arr);
    }

    //对希尔排序进行优化->移动法
    public static void shellsort(int[] arr){
        int count=0;
        //缩小增量gap
        for(int gap=arr.length/2;gap>0;gap=gap/2){
            //从第gap个元素,逐个对其所在的组进行直接插入排序
            for (int i = gap; i < arr.length; i++) {
                int j=i;//保存位置下标
                int temp=arr[j];//保存第一个找到的数组元素
                if(arr[j-gap]>arr[j]){
                    while(j-gap>=0&&temp<arr[j-gap]){
                        //不直接进行交换而是进行移动
                        arr[j]=arr[j-gap];
                        j-=gap;
                    }
                    //当退出while循环后,代表找到了temp插入的位置
                    arr[j]=temp;
                }
            }
            System.out.println("希尔排序第"+(++count)+"轮结果为"+ Arrays.toString(arr));
        }
    }
}

二、归并排序

在这里插入图片描述
在这里插入图片描述

package 归并排序;

import java.util.Arrays;

public class test {
    public static void main(String[] args) {
        int[] arr={8,4,5,7,1,3,6,2};
        int[] temp=new int[arr.length];
        mergesort(arr,0,arr.length-1,temp);

        System.out.println("归并排序后的结果为"+ Arrays.toString(arr));
    }

    //分+合的方法
    public static void mergesort(int[] arr,int left,int right,int[] temp){
        if(left<right){
            int mid=(left + right)/2;
            //向左递归进行分解
            mergesort(arr,left,mid,temp);
            //向右递归进行分解
            mergesort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

    //合并的方法
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i=left;//初始化i,左边有序序列的初始索引
        int j=mid+1;//初始化j,右边有序序列的初始索引
        int t=0;//指向temp数组的当前索引

        //(一)
        //先把左右两边的有序序列按照规则填充到temp数组中
        //直到两边的有序序列,有一边处理完毕为止
        while(i<=mid&&j<=right){
            //如果左边的有序序列的当前元素小于右边序列的当前元素
            //则将左边的当前元素,拷贝到temp数组中
            if(arr[i]<=arr[j]){
                temp[t]=arr[i];
                t+=1;
                i+=1;
            }else{//反之,则将右边的当前元素,拷贝到temp数组中
                temp[t]=arr[j];
                t+=1;
                j+=1;
            }
        }
        //(二)
        //把有剩余数据的一边的数据依次填充到temp数组中
        while(i<=mid){//左边有剩余
             temp[t]=arr[i];
             t+=1;
             i+=1;
        }
        while(j<=right){//右边有剩余
            temp[t]=arr[j];
            t+=1;
            j+=1;
        }

        //(三)
        //将temp数组中的数据拷贝到arr
        //注意,不是每次都拷贝所有
        t=0;
        int templeft=left;
        System.out.println("templeft="+templeft+"right="+right);
        while(templeft<=right){
            //第一次合并templeft=0,right=1//tl=2,ri=3//tl=0,ri=3;
            //最后一次合并tl=0,ri=7
            arr[templeft]=temp[t];
            t+=1;
            templeft+=1;
        }
    }
}

在这里插入图片描述

三、 基数排序

在这里插入图片描述

package 基数排序;

import java.util.Arrays;

public class test {
    public static void main(String[] args) {
        int[] arr={53,3,542,748,14,214};
        radixSort(arr);
    }
    public static void radixSort(int[] arr){
        //1、遍历数组,得到数组中最大的元素
        int max=arr[0];
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]>max){
                max=arr[i];
            }
        }
        //得到最大数是几位数
        int maxLength=(max+"").length();//将数字转化成字符串,使得可以使用length方法

        //定义一个二维数组
        //说明
        //1、二维数组包含10个一维元素
        //2、为防止数据溢出,则每一个一维数组(桶),大小定为arr.length
        //3、基数排序是经典的空间换时间的算法
        int[][] bucket=new int[10][arr.length];

        //为了记录每个桶中实际放了多少个元素,我们定义一个一维数组来记录各个桶的每次放入的数据个数
        //比如:bucketElementCounts[0],记录的就是bucket[0]桶中放入数据个数
        int[] bucketElementCounts=new int[10];

        //使用循环对代码进行处理
        for (int i = 0, n=1; i < maxLength; i++, n *= 10) {
            //针对每个元素的对应位进行排序处理,第一次是个位,第二次是十位,第三次是百位
            for (int i1 = 0; i1 < arr.length; i1++) {
                //取出每个元素的对应位的值
                int digitOfElement = arr[i1] / n % 10;
                //放入到对应的桶中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i1];
                bucketElementCounts[digitOfElement]++;
            }

            //按照这个桶的顺序(一维数组的下标依次取出数据,放入到原来数组中)
            int index = 0;
            //遍历每一桶,并将桶中的数据放入到原数组中
            for (int k = 0; k < bucketElementCounts.length; k++) {
                //如果桶中有数据,我们才放到原数组中
                if (bucketElementCounts[k] != 0) {
                    //循环该桶即第k个桶(即第k个一维数组)放入
                    for (int l = 0; l < bucketElementCounts[k]; l++) {
                        arr[index] = bucket[k][l];
                        index++;//数组下标+1,然后放入第k个桶的下一个元素
                    }
                }
                //第i+1轮数据处理后,需要将每个bucketElementCounts[k]=0!!!
                bucketElementCounts[k] = 0;
            }
            System.out.println("第" +(i+1)+"轮,的排序处理是"+ Arrays.toString(arr));
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值