八大排序算法详解,java代码实现

class Sort{
    //冒泡排序
    public void Effervescence(int[] arr){
        //核心思想是两两交换,每轮将最大的数交换到后面
        for(int i = 0;i<arr.length-1;i++)
        {
            //每轮最大数放后面,j的边界变小
            for(int j = 0;j<arr.length-1-i;j++)
            {
                if(arr[j]>arr[j+1])
                {
                    //如果后面比前面小就交换
                    int t = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = t;
                }
            }
        }
    }
    //选择排序
    public static void Choose(int[] arr){
        //核心思想是遍历找最小值,放在最前面,然后又从后面找
        for(int i = 0;i<arr.length-1;i++)
        {
            int k = i;
            int min = arr[i];
            for(int j = i+1;j<arr.length;j++)
            {
                if(arr[j]<min)
                {
                    min = arr[j];
                    k = j;
                }
            }
            if(k != i)
            {
                int t = arr[i];
                arr[i] = arr[k];
                arr[k] = t;
            }
        }
    }
    //插入排序
    public static void Insert(int[] arr){
        //核心思想是将一个大小为n数组分为两表,前面有x个有序数后面有n-x个无序数
        //从无序数里面找一个有序数插到有序数里面
        for(int i = 1;i<arr.length;i++)
        {
            int val = arr[i];//获取当前值并保存
            int index = i-1;//应该插入的下标
            while(index>=0&&arr[index]>val)//直到该插入的位置的值比当前值小或越界则退出
            {
                arr[index+1] = arr[index];//将之前的值往后移
                index--;
            }
            arr[index+1] = val;
        }
    }
    //希尔排序_交换式
    public static void Shell_Exchange(int[] arr){
        //核心思想是在快排基础上进行优化
        //将数组分组进行插入排序
        //当步长gap<=0是退出
        for(int gap = arr.length/2;gap>0;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])
                    {
                        //shell交换式本质是冒泡
                        int t = arr[j];
                        arr[j] = arr[j+gap];
                        arr[j+gap] = t;
                    }
                }
            }
        }
    }
    //希尔排序_移位式
    public static void Shell_translocation(int[] arr){
        //核心思想就是分组使用插入排序
        for(int gap = arr.length/2;gap>0;gap/=2)
        {
            //分组
            for(int i = gap;i<arr.length;i++)
            {
                int j = i;
                int val = arr[i];
                //保留当前值
                if(val<arr[j-gap])
                {
                    while(j-gap>=0&&val<arr[j-gap])
                    {
                        arr[j] = arr[j-gap];//移位
                        j-=gap;
                    }
                    arr[j] = val;//找到下标
                }
            }
        }
    }
    //快速排序
    public static void Quick(int[] arr,int low,int high){
        //快排的核心思想是分治法
        //选择一个支点将比该支点小的放左边,比支点大的放右边

        //被分割为1,退出
        if(low>=high)
            return;

        int prvot = arr[low];//选择第一个为支点
        int l = low;//定义左右指针
        int r = high;
        while(l<r)
        {
            while(l<r&&prvot<=arr[r])
                r--;
            arr[l] = arr[r];//移步,插入排序思想
            while(l<r&&prvot>=arr[l])
                l++;
            arr[r] = arr[l];
        }
        arr[l] = prvot;
        Quick(arr,low,l-1);//递归,将左右两边排序
        Quick(arr,r+1,high);
    }
    //归并排序
    public static void Recursive_Merge(int[] arr,int low,int high,int[] temp){
        //归并排序的思想也是分治法
        //将一个大数组递归分成很多个小数组,将小数组排序后合并
        if(low<high)
        {
            int mid = (low+high)/2;
            Recursive_Merge(arr,low,mid,temp);//左边分
            Recursive_Merge(arr,mid+1,high,temp);//右边分
            Merge(arr,low,mid,high,temp);//合并治
        }
    }
    public static void Merge(int[] arr,int low,int mid,int high,int[] temp){
        int a = low;
        int b = mid+1;//双指针
        int index = low;
        //开始合并两个有序数组
        while(a<=mid&&b<=high)
        {
            if(arr[a]<=arr[b])
            {
                temp[index++] = arr[a++];
            }
            else
            {
                temp[index++] = arr[b++];
            }
        }
        while(a<=mid)
            temp[index++] = arr[a++];
        while(b<=high)
            temp[index++] = arr[b++];
        //临时数组保存两个排序后的有序数组
        for(int i = low;i<=high;i++)
        {
            arr[i] = temp[i];
        }
    }
    //基数排序
    public static void Radix(int[] arr){
        //核心思想就是每次比较各位,再排序
        //桶排序升级版
        //空间换时间算法
        int max = arr[0];
        for(int i = 1;i<arr.length;i++)
        {
            if(arr[i]>max)
                max = arr[i];
        }
        int maxLength = (""+max).length();
        //统计最大数位数,确定循环次数

        int[][] bucket = new int[10][arr.length];//初始化十个桶
        int[] bucketElementsCount  = new int[10];//统计每个桶的元素个数

        for(int t = 0;t<maxLength;t++)//总循环次数
        {
            for(int i = 0;i<arr.length;i++)
            {
                int num = arr[i]/(int)Math.pow(10,t)%10;//取得当前该位数
                bucket[num][bucketElementsCount[num]++] = arr[i];//讲其对应数放在桶中
            }
            int index = 0;//原数组重新赋值,定义下标
            for(int k = 0;k<bucketElementsCount.length;k++)
            {
                for(int l = 0;l<bucketElementsCount[k];l++)
                {
                    arr[index++] = bucket[k][l];
                }
                bucketElementsCount[k] = 0;//桶元素个数指针重置
            }
        }
    }
    //堆排序
    public static void Heap(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        int len = arr.length;
        // 构建大顶堆,这里其实就是把待排序序列,变成一个大顶堆结构的数组
        buildMaxHeap(arr, len);

        // 交换堆顶和当前末尾的节点,重置大顶堆
        for (int i = len - 1; i > 0; i--) {
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            len--;
            heapify(arr, 0, len);
        }
    }

    private static void buildMaxHeap(int[] arr, int len) {
        // 从最后一个非叶节点开始向前遍历,调整节点性质,使之成为大顶堆
        for (int i = (int)Math.floor(len / 2) - 1; i >= 0; i--) {
            heapify(arr, i, len);
        }
    }

    private static void heapify(int[] arr, int i, int len) {
        // 先根据堆性质,找出它左右节点的索引
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        // 默认当前节点(父节点)是最大值。
        int largestIndex = i;
        if (left < len && arr[left] > arr[largestIndex]) {
            // 如果有左节点,并且左节点的值更大,更新最大值的索引
            largestIndex = left;
        }
        if (right < len && arr[right] > arr[largestIndex]) {
            // 如果有右节点,并且右节点的值更大,更新最大值的索引
            largestIndex = right;
        }

        if (largestIndex != i) {
            // 如果最大值不是当前非叶子节点的值,那么就把当前节点和最大值的子节点值互换
            int temp = arr[i];
            arr[i] = arr[largestIndex];
            arr[largestIndex] = temp;
            // 因为互换之后,子节点的值变了,如果该子节点也有自己的子节点,仍需要再次调整。
            heapify(arr, largestIndex, len);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值