ACM算法笔记(七)排序算法【下】

一、归并排序

对给定的数据,利用递归和分治的技术将数据序列划分为越来越小的半子表;对半子表排序后在利用递归算法将排序好的半子表进行合并

                半子表小于一定规模(一般为15)时可以直接插入排序等算法提高性能(不再递归)。

                拆分的时候可以进行多路拆分,称为X路排序

public int[] MergeSort(int[] arr)
{
    if(arr.length<2)
        return arr;    //递归终止条件

    int mid = arr.length/2;
    int[] left = Arrays.copyOfRange(arr,0,mid);//进行切割
    int[] right= Arrays.copyOfRange(arr,mid,arr.length);//进行切割

    return merge(MergeSort(left),MergeSort(rigth));//进行递归+合并
}

//合并,类似于差值比较
public int[] merge(int[] left,int[] right)
{
    int[] result = new int[left.length+right.length];
    
    for(int index = 0,i = 0,j = 0; index < result.lenght; index++)
    {
        if(i >= left.length)//左边已取完
            result[index] = right[j++];
        else if(j >= right.length)//右边已取完
            result[index] = left[i++]

    //比较算法
        else if(left[i]>right[j])
            result[index] = right[j++];
        else
            result[index] = left[i++];
    }
    return result;
}

二、堆排序

        需要处理有序数据,但是不要求全部有序(可能仅需要操作最大的元素),可以使用二叉堆进行排序

        二叉堆是一个完全二叉树,同时还满足堆的概念(子节点的value总小于/大于其父节点),对于这种堆,可以称为最大/小堆

        由于完全二叉树的特性,可以用一个数组表示其结构(从小到大,且仅有两个结点)

        其中最后一个非叶节点为(N/2)-1

         思路:    ①将最后一个非叶节点和其叶子节点进行比较+交换

                        ②倒序的将非叶节点与其左右孩子进行比较+交换

                                ↑完成完全二叉堆   ↓堆排序

                        ③将堆顶元素尾元素进行交换

                        ④将尾元素进行脱离,对剩下的二叉树重复①~④

                        通过此操作可以使堆顶元素(最大/小值)不断剥离

public int[] SortArry(int[] arr)
{
    len = arr.length;
    if(len<1) return arr;

    //构建最大堆
    BuildMaxHeap(arr);
    //将堆顶元素与末尾元素进行交换并脱出
    while( len>0)
    {
        swap(arr,0,len-1);//交换
        len--
        AdjustHeap(arr,0);//调整为最大堆
    }
}

public int[] BuildMaxHeap(int[] arr)
{
    //从最后一个非叶子节点开始向上构造最大堆
    for(int i = l(len/2-1); i>-0; i--)
        AdjustHeap(arr,i);
}

public void AdjustHeap(int[] arr,int i)
{
    int maxIndex = i;
    int left = 2*i+1;
    int right = 2*(i+1);
    
    //依次比较子树中最大的节点并进行交换
    if(left < len && arr[left]>arr[maxIndex])
        maxIndex = left;
    if(right <len && arr[right]>arr[maxIndex] && arr[right]>arr[left])
        maxIndex = right;
    if(maxIndex != i)
        {
            swap(arr,maxIndex,i);
            AdjustHeap(arr,maxIndex);
        }
}

三、计数排序

        计数排序、基数排序、桶排序均利用了桶排序的概念,但是在桶的使用上有差异

        计数排序在排序过程中并不比较元素大小,适用于一定范围内(待排序元素较为连续且跨度较小)的整数排序

         步骤:    ①初始化一个计数数组(max+1)

                        ②遍历原始数组,将原始数组中的每个元素转换为对应的下标,并将其对应的计数元素+1(例如某数组内有6个值为3的数,则将计数数组下标为3的元素置为6)

                        ③遍历计数数组,若当前计数元素不为0,则将当前原始数组元素置位下标;同事计数元素值-1,原始数组指针+1,循环往复

         代码略

四、桶排序

        桶排序是计数排序的升级版

        工作原理:假设此数据服从均匀分布,将数据分到有限数量的桶里,在从桶中分别排序,排序完成后再合成一个排序后序列

        先确立桶的容量,再根据元素的个数确定桶的个数

         代码略

五、基数排序

        思路:将元素中的所有元素分别按照不同的位数入桶(有几位就入桶几次),每次入桶后形成一个新的序列

         代码略

六、排序算法总结

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值