编程珠玑第九章--性能之代码调优

本文探讨了多种二分搜索算法实现方式,并对比了两种位运算计数方法,提出了一种利用哈希映射进行优化的策略。同时,介绍了如何通过哨兵元素查找最大值,以及如何从数学角度优化多项式计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大手术–二分搜索
几个程序的书写

package chapter9;


public class BinarySort {
    public static int binarySort0(int x[],int number){
        int l=0,r=x.length-1;
        int m=0;
        while(true){
            if(l>r){
                return -1;
            }
            m=(l+r)/2;
            if(x[m]>number){
                r=m-1;
            }
            if(x[m]==number){
                return m;
            }
            if(x[m]<number){
                l=m+1;
            }
        }
    }
    //我们假定x[-1]<t;x[n]=>t只是假想并不实际进行访问这两个元素;然后在循环进入条件l+1!=m,并且根据m=(l+r)/2;通过对x[m]与number的比较,不断更新l或r,使得x[l]<t,x[r]>=t始终成立,甚至最终l+1=m跳出循环时仍然成立,此时看一下r是否为所求下标;
    public static int binarySort1(int x[],int number){
        int l=-1,r=x.length;
        while(l+1!=r){
            int m=(l+r)/2;
            if(x[m]<number){
                l=m;
            }
            else {
                r=m;
            }
        }
        if(r>=x.length||x[r]!=number)//r>=x.length保证不会访问x[n];
            return -1;
        else {
            return r;
        }
    }
    //假设n=1000;程序里我们不使用l,r表示数组的左右边界;而是使用l+i来表示右边界,
    //所以就要使得l+i=r,并且我们要是i是2的正整数次 ;
    public static int binarySort2_a(int x[],int number){
        int i=512;
        int l=-1;
        if(x[511]<number){
            l=1000-i;//确保l...l+incremnt要么为-1...511,要么是488...512;
        }
        int next_i;
        while(i!=1){
            //循环不变式:x[l]<number&&x[l+i]>=number&&i=2^j;
             next_i=i/2;
            if(x[l+next_i]<number){
                l+=next_i;
                i=next_i;
            }
            else {
                i=next_i;
            }
        }
//      assert(i==1&&x[l]<number&&x[l+i]>=number);
        int p=l+1;
        if(p>1000||x[p]!=number){
            return -1;
        }
        return p;
    }
    public static int binarySort2_b(int x[],int number){
        int i=512;
        int l=-1;
        if(x[511]<number){
            l=1000-i;//确保l...l+incremnt要么为-1...511,要么是488...512;
        }
        while(i!=1){
            //循环不变式:x[l]<number&&x[l+i]>=number&&i=2^j;
             i=i/2;
            if(x[l+i]<number){
                l+=i;
            }
        }
//      assert(i==1&&x[l]<number&&x[l+i]>=number);
        int p=l+1;
        if(p>1000||x[p]!=number){
            return -1;
        }
        return p;
    }
    public static int binarySort3(int x[],int number){
        int i=512;
        int l=-1;
        if(x[511]<number){
            l=1000-i;//确保l...l+incremnt要么为-1...511,要么是488...512;
        }
        if(x[l+256]<number)l+=256;
        if(x[l+128]<number)l+=128;
        if(x[l+64]<number)l+=64;
        if(x[l+32]<number)l+=32;
        if(x[l+16]<number)l+=16;
        if(x[l+8]<number)l+=8;
        if(x[l+4]<number)l+=4;
        if(x[l+2]<number)l+=2;
        if(x[l+1]<number)l+=1;
//      assert(i==1&&x[l]<number&&x[l+i]>=number);
        int p=l+1;
        if(p>1000||x[p]!=number){
            return -1;
        }
        return p;
    }
}

习题
6.0~9,a~z,A~Z看它属于哪一个范围
7.先设计算法计算每一个输入单元,int 或者是char;
对于int,方法一:number&(1<

package chapter9;

import java.util.HashMap;
public class t7 {
    //因为Java里int为32位,并且只有有符号数只能访问到31位
    //方法一:number&(1<<i);找到对应的每一位的值,

    //当然这个方法对于每个int都要运行31次
    public static int countInt0( int number){
        int temp=0;
        int count=0;
        for(int i=0;i<31;i++){
            temp=number&(1<<i);
            //          System.out.print(temp+" ");
            if(temp!=0){//事实上,temp应该等于1<<i;才会进行count++
                count++;
            }
        }
        //      System.out.println();
        return count;
    }
    //方法二:使用number&=(number-1),对number中是1的位进行迭代,直到b==0,跳出循环
    //可以看出方法二运行的次数就是number中位为1的个数,比方法一肯定是快的;
    public static int countInt1(int number){
        int count=0;
        while(number>0){
            number&=(number-1);
            //          System.out.print(number+" ");
            count++;
        }
        //      System.out.println();
        return count;
    }
    //对于字符位为1的个数,只需将字符转换成int就好,然后就利用countInt1可以直接来算
    public static int countChar(char c){
        int re=Integer.valueOf(c);
        //      System.out.println(re);
        return countInt1(re);

    }
    //优化是用一个HashMap进行保存各个数字及其位为1的个数,键位数字+""或者字符+"",值为个数;
    //对于每一个数先看hashmap里是否包含,若是包含就直接取值,若是不包含则使用上述的方法二countInt1进行计算并保存
    static HashMap<String, Integer> hashMap=new HashMap<String, Integer>();
    //当然另一种优化就是看看对所有输入单元进行统计,看看每一个单元出现的次数,然后存储下次数,最后对于不同的单元计算其1出现的个数并乘以个数,最后相加
    //其实和上面的优化的效率差不多
    public static long countExample(){
        int arr[]={31,31,30,30};
        char cArr[]="aabb".toCharArray();
        long count=0;
        int temp;
        for(int i=0;i<arr.length;i++){
            if(!hashMap.containsKey(arr[i]+"")){
                temp=countInt1(arr[i]);
                count+=temp;
                hashMap.put(arr[i]+"", temp);
                System.out.println("store "+arr[i]);
            }
            else {
                count+=hashMap.get(arr[i]+"");
                System.out.println("from the store ");
            }
        }
        for(int i=0;i<cArr.length;i++){
            if(!hashMap.containsKey(cArr[i]+"")){
                temp=countChar(cArr[i]);
                count+=temp;
                hashMap.put(cArr[i]+"", temp);
                System.out.println("store "+cArr[i]);
            }
            else {
                count+=hashMap.get(cArr[i]+"");
                System.out.println("from the store ");
            }
        }
        return count;

    }
    public static void main(String args[]){
        //      System.out.println(Integer.SIZE);
        //      System.out.println(Integer.MAX_VALUE);
        //      System.out.println(Integer.MIN_VALUE);
        //      System.out.println(Character.SIZE);//0000-FFFF 16位
        //      System.out.println(Character.MIN_VALUE+" ");
        //  System.out.println("方法一");
        //  System.out.println(countInt0(255));
        //  System.out.println(countInt0(254));
        //  System.out.println(countInt0(253));
        //  System.out.println(countInt0(1023));
        //  System.out.println(countInt0(1022));
        //  System.out.println(countInt0(1021));
        //  System.out.println("\n\n");
        //  System.out.println("方法二");
        //  System.out.println(countInt1(255));
        //  System.out.println(countInt1(254));
        //  System.out.println(countInt1(253));
        //  System.out.println(countInt1(1023));
        //  System.out.println(countInt1(1022));
        //  System.out.println(countInt1(1021));
        //  System.out.println("\n\n");
        //      System.out.println("count char");
        //      System.out.println(countChar('a'));
        System.out.println(countExample());
    }
}

运行结果

store 31
from the store 
store 30
from the store 
store a
from the store 
store b
from the store 
30

8.利用哨兵元素寻找最大值
*

package chapter9;
public class t8 {
    public static int findMax(int arr[]){
//      arr[arr.length-1]用来作为哨兵元素
        int i=0;
        int n=arr.length-1;
        int max=0;
        while(i<n){
            max=arr[i];
            arr[n]=max;
            i++;
            while(arr[i]<max){
                i++;//直到找到比现在max大或等于的;或者最终i==n,找到哨兵,跳出循环
            }
        }
        return max;
    }
public static void main(String args[]){
    System.out.println(findMax(new int[]{5,4,3,3,1}));
}
}

11.因为只需要角度为5度的整数倍时才需要计算。360/5=72;因为0与360是等价的,所以只需要取其一即可。所以只要利用表格记录角度为0,5,10,15,…….,355对应的三角函数值即可
12.人们在调优程序时有时会从数学的角度而不是代码的角度看问题。

package chapter9;

public class t12 {
    public static int compute(int a[],int x){
        int y=a[0];
        int n=a.length-1;
        int temp=1;
        for(int i=1;i<=n;i++){
            temp=x*temp;
            y+=a[i]*temp;
//          System.out.print(y+" ");
        }
//      System.out.println();
        return y;
    }
    public static int compute1(int a[],int x){
        int n=a.length-1;
        int y=a[n];
        for(int i=n-1;i>=0;i--){
            y=x*y+a[i];//利用n次乘法,按需要与x的乘积次数将a数组里的元素一一放入,进行乘积
        }
        return y;

    }
    public static void main(String args[]){
        System.out.println(compute(new int[]{1,1,1,1,1}, 2));
        System.out.println(compute1(new int[]{1,1,1,1,1}, 2));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值