【算法】基础算法——排序

1、快排

  • 复杂度O(nlogn)
  • 不稳定
  • 思路是通过一趟排序将数组分为两部分,其中一部分的所有数比另一部分的所有数都小,再递归对这两部分进行排序,达到全部排序的目的
  • 一趟排序具体过程是从待排序列中任意选取一个记录(通常选取第一个记录)作为基准值,然后将比它小的值都放在它的位置之前,将比它大的都放在它的位置之后。这样,以该基准值为分界线,将待排序列分成的两个子序列
  • 一趟排序的具体做法:设置两个指针low和high分别指向待排序列的开始和结尾,记录下基准值baseval(待排序列的第一个记录),然后先从high所指的位置向前搜索直到找到一个小于baseval的记录并互相交换,接着从low所指向的位置向后搜索直到找到一个大于baseval的记录并互相交换,重复这两个步骤直到low=high为止
public void quick(int[] nums, int start, int end){
        if (start >= end)    return;   //如果左边界大于等于右边界,就不用排了
        int i = start;
        int j = end;
        
        //记录基准数
        int val = nums[start];
        while (i < j){
            //每次从右向左找一个比基准数小的数
            while (j > i && nums[j] > val){
                j--;
            }
            if (j > i){        //如果找到了,就把这个值赋值到前面去,前指针往后挪
                nums[i] = nums[j];
                i++;
            }
            
            //每次从左向右找一个比基准数大的数
            while (i < j && nums[i] < val){
                i++;
            }
            if(i < j){        //如果找到了,就把这个值复制到后边去,后指针往前挪
                nums[j] = nums[i];
                j--;
            }           
        }
        
        nums[i] = val;
        quick(nums, start, i-1);
        quick(nums, i+1, end);
    }

2、堆排序

  • 复杂度O(nlogn)
  • 不稳定
  • 思路:大顶堆是任一节点大于它的左右子节点,小顶堆是任一节点小于它的左右子节点。将待排序列构造成一个大顶堆(或小顶堆),整个序列的最大值(或最小值)就是堆顶的根结点,将根节点的值和堆数组的末尾元素交换,此时末尾元素就是最大值(或最小值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值(或次小值),如此反复执行,最终得到一个有序序列
public void heap(int[] nums){
        int length = nums.length;
        // 初始化堆
        // length / 2 - 1是二叉树中最后一个非叶子结点的序号,因为叶子节点没有左右儿子,不需要调整
        for (int i = length / 2 - 1; i >= 0; i--)
        {
            HeapAdjust(nums, i, length);
        }	//到这里构成了一个大顶堆
        
        // 交换堆顶元素和最后一个元素,也就是出堆过程,取最大的存起来,较小的沉到相应的位置去
        for (int i = length - 1; i >= 0; i--){
            int temp;
            temp = nums[i];
            nums[i] = nums[0];
            nums[0] = temp;
            HeapAdjust(nums, 0, i);
        }
    }
    
    //分别是数组,需要调整的下标值,数组长度
    void HeapAdjust(int nums[], int i, int length)
    {
        // 调整i位置的结点
        // 先保存当前结点的下标
        int max = i;
        // 当前结点左右孩子结点的下标
        int lchild = i * 2 + 1;
        int rchild = i * 2 + 2;
        if (lchild < length && nums[lchild] > nums[max])
        {
            max = lchild;
        }
        if (rchild < length && nums[rchild] > nums[max])
        {
            max = rchild;
        }//到这里得到了i位置节点和他左右儿子三个中的最大值的下标
        // 若i处的值比其左右孩子结点的值小,就将其和最大值进行交换
        if (max != i){
            int temp;
            temp = nums[i];
            nums[i] = nums[max];
            nums[max] = temp;
            // 递归,调整下面的堆
            HeapAdjust(nums, max, length);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值