• 编程珠玑第一章习题


    第一章习题1解析

    以下代码均使用MSVC 6.0编译运行通过,为了便于学习,在原代码的基础上进行了一定的修改。

    1.如何使用一个具有库的语言来实现一种排序算法以表示和排序集合,将代码实现可用

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int comp(const void *x,const void *y){
     4     return (*(int*)x-*(int*)y);
     5 }
     6 int a[5]={45,25,64,10,4};
     7 void main(){
     8     int i,n=0;
     9     printf("排序前列表为:
    ");
    10     for(i=0;i<5;i++){
    11         printf("%d
    ",a[i]);
    12     }        
    13     qsort(a,5,sizeof(int),comp);
    14     printf("排序后列表为:
    ");
    15     for(i=0;i<5;i++){
    16         printf("%d
    ",a[i]);    
    17     }
    18 
    19 }

    在使用原书中代码会报错:

    int intcomp(int *x,int *y){
      return *x-*y;  
    }

    error C2664: 'qsort' : cannot convert parameter 4 from 'int (int *,int *)' to 'int (__cdecl *)(const void *,const void *)'
    None of the functions with this name in scope match the target type

    意思是不能把int (int *,int *)自动转换为int (__cdecl *)(const void *,const void *),按提示错误,在声明函数时改写为上述函数正确写法即可。

     用C++标准模板库中的set容器完成相同的任务:

    #include <iostream>
    #include<set>
    using namespace std;
    int main(void){
        set<int> S;
        int i,n;
        cin>>n;
        for(i=0;i<n;i++){
            int x;
            cin>>x;
            S.insert(x);
        }
        set<int>::iterator j;//迭代器用于遍历    
        for(j=S.begin();j!=S.end();j++)
            cout<<*j<<"
    ";
         //s.end()没有值
        //s.begin()返回容器的第一个元素
         cout<<"s.begin()   "<<*S.begin ()<<endl;
        //lower_bound()返回第一个大于或等于给定关键值的元素
        cout<<"lower_buond 10 "<<*S.lower_bound (10)<<endl;    
        //upper_bound()返回第一个大于给定关键值的元素
        cout<<"upper_bound 10 "<<*S.upper_bound (10)<<endl;
        //find()查找一个元素,如果容器中不存在该元素,返回值等于s.end()
        cout<<"find() 10 "<<*S.find (10)<<endl;
       if(S.empty())
            cout<<"容器为空"<<endl;
        if(S.count(10))
            cout<<"10在容器中"<<endl;

       cout<<"s.size() "<<S.size ()<<endl; return 0; }

    2和3

    这方法太巧妙了,先来讲解以下使用常量来设置、清除以及测试位值

    #define BITSPERWORD 32
    #define SHIFT 5
    #define MASK 0x1F
    #define N 10000000
    int a[1+N/BITSPERWORD];
    void set(int i){a[i>>SHIFT]|=(1<<(i&MASK));}//指定bit位设为1
    void clr(int i){a[i>>SHIFT]&=~(1<<(i&MASK));}//指定bit位设为0
    int test(int i){return a[i>>SHIFT]&(1<<(i&MASK));}//取存入的值,5bit一组

    补充C++运算符知识:

    <<二进制左移运算符。左操作数的值向左移动右操作数指定的位数。如A原十进制值为60,二进制值为00111100,A << 2 将得到 240,即为 1111 0000

    相当于60*4,也就是A*2*2,右移相当于做乘法

    >>二进制右移运算符。左操作数的值向右移动右操作数指定的位数。A >> 2 将得到 15,即为 0000 1111

    相当于60/4,也就是A/2*2,左移相当于做除法

    2的倍数的乘除法用位移实现

    &如果同时存在于两个操作数中,二进制 AND 运算符复制一位到结果中。给定B为13,二进制值为00001101,则(A & B) 将得到 12,即为 0000 1100

    那么i&0x1f,0x1f十进制值为31,二进制值00011111,当一个数和该数做&运算,如果余数在二进制位有值,则结果位是1,否则为1。

    &得到的是32的余数。

    void set(int i){a[i/32]|=(1<<(i%32));}
    void clr(int i){a[i/32]&=~(1<<(i%32));}
    int test(int i){a[i/32]&(i<<(i%32));}

    用2的5次方也就是32的原因是,int型为4个字节,32位,a为 int型数组,那么除以32可以知道是a数组中哪一个下标,32取模得到的是int具体的某一位

    我的理解是这样的:

     因此,a[i>>SHIFT]是第i位代表数组a的第几个int型数上  (1<<(i & MASK))是第i位在该int上的第几位上、

    set将数组a中第几个int的数的第几个位(bit)赋值为1,clr赋值为0,test用于遍历。

    整体代码思路是先将数组中的每个int数的bit位清零,然后循环输入数值,bit位赋值1,最后遍历输出。位图如示意图显示。

     修订可运行代码:

    #include<stdio.h>
    #define BITSPERWORD 32
    #define SHIFT 5
    #define MASK 0x1F
    #define N 128
    int a[1+4];
    void set(int i){a[i>>SHIFT]|=(1<<(i&MASK));}
    void clr(int i){a[i>>SHIFT]&=~(1<<(i&MASK));}
    int test(int i){return a[i>>SHIFT]&(1<<(i&MASK));}
    int main(void){
        int i;
        for(i=0;i<N;i++)
            clr(i);
        printf("请输入4个数");
        for(int j=0;j<4;j++)
        {
            scanf("%d",&i);
            set(i);
        }        
        for(i=0;i<N;i++)
            if(test(i))
                printf("%d
    ",i);
        return 0;
    }
    View Code

    此题解参考了https://blog.csdn.net/xuzhengzheng32/article/details/15026637给出的方法并进行修正补充

     最后分析十分精妙:当n为10000000,且输入文件包含1000000个整数时,通用C++程序所需的内促成你和CPU时间是专用C程序的50倍,但是代码量仅有C程序的一半

    该方法有个问题是,当有重复值出现时,结果只保存一次该值,也就是只输出一次该值

  • 相关阅读:
    .Maven的工程类型有哪些?
    .Maven仓库是什么
    什么是Maven?
    .request.getAttribute()和 request.getParameter()有何区别?
    .什么是CDN?哪些是流行的jQuery CDN?使用CDN有什么好处?
    .window.onload()函数和jQuery中的document.ready()有什么区别?
    get和post的区别?
    Maven常用命令有哪些?
    物质待遇和工作条件是人们选择工作的重要因素之一,这次报考谈一谈你在选择工作时都考虑哪些因素?为什么?
    你最大的长处和弱点分别是什么?这些长处和弱点对你在企业的业绩会有什么样的影响?
  • 原文地址:https://www.cnblogs.com/juranus1412/p/12590235.html
Copyright © 2020-2023  润新知