编码中的小技巧之防止数据溢出

写出正确的代码是技术,写出优美的代码时艺术。

前两天在看排序算法,其中看到归并排序的时候,发现一个编码的技巧。
我先复习一下,归并排序先吧。
分析: 归并排序采用分治的思想。将一个大问题分解若干个子问题,子问题与 原问题,解决的方式是一样的,并且子问题是独立的即子问题之间没有关系,最小的子问题是有解的并且好解。这里是不是很想我们学过的递归。

分治是一种解题思路,递归是一种编码技巧。

这里具体时这样实现的,将未排序的数据分为有序的两部分,然后对这两部分进行排序。而对于被分为两部分的数据,再各自当作原问题,按照刚刚的思路,分为两部分有序的数据,直到数据大小唯一的时候。

即:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

Take is cheap .Show me the code .

代码

import java.util.Arrays;

public class MergeSort {

   public static void main(String[] args) {
       int n = 100;
       int [] a = new int[n];

       for(int i = 0;i<n;i++){
           a[i] = (int)(Math.random()*n);
       }

       System.out.println(Arrays.toString(a));
       mergeSort(a,0,a.length-1);
       System.out.println(Arrays.toString(a));
   }

   public static void mergeSort(int[] A,int p ,int r){
       /*归并排序是建立在归并操作上的一种有效的排序算法。
       该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
       将已有序的子序列合并,得到完全有序的序列;
       即先使每个子序列有序,再使子序列段间有序
       算法描述:
       把长度为n的输入序列分成两个长度为n/2的子序列;
       对这两个子序列分别采用归并排序;
       将两个排序好的子序列合并成一个最终的排序序列。
                   * */
       if(p >= r)
           return ;
       //防止 (r+p)溢出
       int q = p + (r - p)/2;

       mergeSort(A,p,q);
       mergeSort(A,q+1,r);

       merge(A,p,q,r);


   }

   private static void merge(int[] A, int p, int q, int r) {
       int i = p;
       int j = q+1;

       int []temp = new int[r-p+1];
       int index = 0;
       while(i <=q && j <=r){
           // 需要 <= 等于号保证 稳定性
           if(A[i] <= A[j]){
               temp[index++] = A[i];
               i++;
           }else{
               temp[index++] = A[j];
               j++;
           }
       }

       //判断那边有剩余 只有一边有剩余 或者 都没有, 先假定是 第一部分 有剩余
       int start = i;
       int end = q;

       // 看是不是 第二部分 有剩余
       if(j <= r){
           start = j;
           end = r;
       }



       //剩余部分拷贝
       while(start <= end){
           temp[index++]  = A[start++];
       }

       //将临时的数组拷贝到 A的(p,r)中
       for( i = 0;i<r-p+1;i++){
           A[p+i] = temp[i];
       }
   }

}

代码其中有一部分

// 取p到r之间的中间位置q,防止(p+r)的和超过int类型最大值
int q = p + (r - p)/2;

看到时候我发现以前自己没有想到过这种问题。
是不是不像平时写的那样 int q = (r+p)/2; 没有考虑到给你的数据大小时合适的,但操作的时候,不自觉的放大了,可能会发生某种问题。

愿我们都能:自身完成确定性增长,面对外界的不确定性,进行“确定增长”。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值