编程珠玑第1章部分课后习题答案注解

作者:Bryant Lei
出处:http://blog.csdn.net/bryantlei

1.如果不缺内存,使用一个具有库的语言来实现一种排序算法。

方法1:利用qsort函数进行排序

C语言版(qsort_c.c):

#include<stdio.h>
#include<stdlib.h>
int compare(int *x, int *y)
{
	return *x > *y ? 1 : -1;
}
int main()
{
	int a[10];
	int i,n = 0;
	while((scanf("%d",&a[n])) != EOF)
		n++;
	qsort(a,n,sizeof(int),intcomp);
	for(i=0; i<n; i++)
		printf("%d ",a[i]);
	return 0;
}

C++版(qsort_c++.cpp)

#include<iostream>
using namespace std;
int compare(const void *x, const void *y)
{
	return *(int *)x - *(int *)y;
}
int main()
{
	int a[10];
	int i,n = 0;
	while((scanf("%d",&a[n])) != EOF)
		n++;
	qsort(a,n,sizeof(int),intcomp);
	for(i=0; i<n; i++)
		printf("%d ",a[i]);
	return 0;
}

注解:

    1.传递合适的参数:

void qsort(

    void *base, //待排序数组首地址

    size_t num, //数组中待排序元素数量

    size_t width, //各元素的占用空间大小

    int compare(const void *, const void *) //指向函数的指针

); 

2.在C中qsort包含在stdlib.h中,c程序中比较函数的写法如下:

int compare(int *x, int *y)

{   

     return *x - *y;

}

3.c++程序中比较函数的写法如下:

int compare(const void *x, const void *y)

{   

return *(int *)x - *(int *)y;

}

4.在C++程序中不能使用第2点中的写法,否则会报error C2664: “qsort”: 不能将参数4 从“int (__cdecl *)(int *,int *)”转换为“int (__cdecl *)(const void *,const void *)”

方法2:利用Java中的sort函数

import java.util.Arrays;
public class SortFunction {
    public static void main(String[] args) {
        int[] array = {9,8,6,7,5,1,3,2,4};
        Arrays.sort(array);//可以对整数数组进行排序
        print(array);
    }
    public static void print(int[] a) {
        for(int i=0; i<a.length; i++)
            System.out.print(a[i] + " ");
        System.out.println();
    }
}
方法3:利用C++标准库的set

#include<iostream>
#include<set>
using namespace std;
int main()
{
	set<int> s;
	int input;
	set<int>::iterator it;
	while(cin >> input)//以EOF结束
		s.insert(input);
	for(it = s.begin(); it != s.end(); ++it)
		cout<<*it<<" ";
	return 0;
}

注解:set会自动将元素进行排序,且不允许重复。

2.使用位图排序,最大整数为10000000,且输入文件包含10000000个整数。

/*
         *使用位图对大量整数排序
         *假设有10000000个整数,最大的数不超过10000000
*/
#include <iostream>
using namespace std;
 
#define BITSPERWORD 32//每个字的位数
#define     SHIFT5
#define MASK 0x1F
#define N 10000000
int a[1 + N/BITSPERWORD];
void set(int i)
{
         a[i/BITSPERWORD]|= (1<<(i & MASK));
}
void clr(int i)
{
         a[i/BITSPERWORD]&= ~(1<<(i & MASK));
}
int test(int i)
{
         returna[i/BITSPERWORD] & (1<<(i & MASK));
}
void print()
{
         for(inti=0; i<)
}
int main()
{
         inti;
         for(i=0;i<N; i++)
                   clr(i);
         while(scanf("%d",&i)!= EOF)
                   set(i);
         for(i=0;i<N; i++)
         {
                   if(test(i))
                            printf("%d", i);
         }
         return0;
}

注解:一开始有点不明白为什么要定义MASK及其(i & MASK),后来想了想,我觉得这应该是为了保持程序的健壮性吧,因为有可能是进行其他的操作。

3.如何生成位于0至n-1之间的k个不同的随机顺序的随机整数?

//生成位于0至n-1之间的k个不同的随机顺序的随机整数
#include <iostream>
#include<time.h>
using namespace std;
#define N 1000
#define random(n) (rand()%n)
#define K 20
int main()
{
         srand((int)time(0));//设置随机数种子,这样的话每次运行结果都不一样,默认是time(1)即每次生成的数都是一样的
    for(int i=0; i<K; i++)
          printf("%d ",random(N));
        
         return0;
}

注解:以下内容转载自http://www.cnblogs.com/kaituorensheng/archive/2013/03/05/2944008.html

C/C++产生随机数用到两个函数rand() 和 srand()

1.不指定范围产生随机数

    用到函数rand(),函数原型为int rand(),无参数。此时会产生一个介于0~RAND_MAX间的整数。RAND_MAX的大小可以查看,在include文件夹(linux在usr目录、windows在安装目录)的stdlib.h可以看到,linux下其值为2147483647(),其值与具体系统有关。

参考代码:

#include<stdio.h>
#include<stdlib.h>
 
int main()
{
       int i;
       for(i=0; i<10; i++)  //随机产生10个数。
       {
           printf("%d\n", rand());
       }
       return 0;
}

二. 指定范围产生随机数,产生0到某个数的随机数

没有现成的函数,但是可以通过取余得到

#include<stdio.h>
#include<stdlib.h>
#define Random(x) (rand() % x) //通过取余取得指定范围的随机数
int main()
{
       int i;
       int dis;               //产生[0, dis)之间的随机数,注意不包括dis
       for(i=0; i<10; i++)
       {   
           printf("%d\n", Random(dis));
       }
       return 0;
}

说明下:假设dis取5,

注意一个问题:以上两个程序每次执行产生的结果是相同的,既是个伪随机数。rand()产生随机数与具体的种子有关,当不特意用srand()获取种子时,种子的默认值为1,因此需要用srand()函数产生不同的种子,srand函数原型:void srand(unsigned seed);为了产生不同的种子值,通常用时间作为参数值。例如对于一,修改程序如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
       int i;
       srand((int)time(NULL));     //每次执行种子不同,生成不同的随机数
       for(i=0; i<10; i++)
       {
         printf("%d\n", rand()); //因为执行太快,不到一秒钟,10个随机数是相通的,但是每次执行是不同的
       }
       return 0;
}

三. 指定范围产生随机数

要求:指定范围(m,n),m、n关系不定,随机数包括m和n

想方设法,把范围(m,n)改变到(0,X),到最后再转移回去。三种情况

1:m=n此时不该叫随机数,这里返回m

2:m>n:

       标记pos=n,距离差pos=m-n+1

     返回 rand() % dis + pos

3:n>m:

       标记pos=m,距离差=n-m+1

     返回rand()%dis + pos

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int Random(int m, int n)
{
       int pos, dis;
       if(m == n)
       {
           return m;
       }
       else if(m > n)
       {
           pos = n;
           dis = m - n + 1;
           return rand() % dis + pos;
       }
       else
       {
           pos = m;
           dis = n - m + 1;
           return rand() % dis + pos;
       }
}
int main()
{
       int i, m, n;
       srand((int)time(NULL));
       m = -3;
       n = -7;
       for(i=0; i<10; i++)
       {
           printf("%d\n", Random(m, n));
       }
       return 0;
}
如有错误,欢迎指正!


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值