编程珠玑——第一章习题解答

本文详细解答了编程珠玑第一章的习题,涉及快速排序算法的实现及其潜在问题,位逻辑运算在实现位向量中的应用,以及位图在排序和数据处理中的效率和优化。通过位图方法解决大整数集合的查找、排序和存储问题,探讨了在有限存储空间内如何提高运行效率,并讨论了如何生成随机顺序的整数序列。此外,还讨论了数据库设计和外太空环境下的书写难题。
摘要由CSDN通过智能技术生成

1、如果不缺内存,如何使用一个具有库的语言来实现以后总排序算法和排序集合?

答:C++有实现排序的库函数:sort。该函数的实现是快速排序。另外C++的容器Map和set均可以实现排序。由于Map和set的实现是红黑树,所以具有自动排序功能。

快速排序算法实现:

void QuickSort(int *array,int left,int right){
	
 int i =left;
 int j = right;
 int temp = array[left];
 if(left>=right)return;
 while(i!=j){
	 while(array[j]>=temp&&i<j)
		j--;
	 if(j>i)
	 array[i]=array[j];
	 while(array[i]<=temp&&i<j)
		 i++;
	 if(i<j)
		 array[j] = array[i];
 }
 array[i] = temp;
 QuickSort(array,left,i-1);
 QuickSort(array,i+1,right);
}
快速排序疑问:

 QuickSort(array,left,i-1);
 QuickSort(array,i,right);

如果改成这样的递归形式,为什么程序会出错??

标准的快速排序一次排序将数组分成三段(左边小于标称值的数组,标称值,右边大于标称值的数组)。如果在递归过程中,如上将数组分成两段(其中一段数组包含标称值),则在算法具体实现的时候会出现问题。

考虑一种特殊的数组 {1,5,6,7,8},这个数组按书上的调用模式QuickSort(array,left,i-1);,QuickSort(array,i,right);;在算法的具体实现中,我们总是将标称值选择为数组的第一个元素。对于这个数组,一次排序之后的结果不变,数组还是{1,5,6,7,8},此时看递归调用的表达形式QuickSort(array,0,-1),QuickSort(array,0,length-1);且不管QuickSort(array,0,-1)这里是否对输入做了边界检查;注意,QuickSort(array,0,length-1),这步递归排序的还是原始的整个数组,这也就意味着递归调用不会有结束的时候,运行程序肯定会出现栈溢出。

实测发现, QuickSort(array,left,i);;QuickSort(array,i+1,right);这样递归调用,程序是没有问题的;此时我们发现表达形式变为了QuickSort(array,0,0),QuickSort(array,1,length-1);其中QuickSort(array,0,0)符合递归的终止条件;QuickSort(array,1,length-1)实际排序的数组长度减了1,那也就意味着递归肯定有结束的时候,所以这个调用在这种快速排序的写法中是没有问题的。但是如果我们将标称值设置为数组的最后一个元素,那么这种写法就会出现栈溢出的情况。

所以,用算法导论上快速排序的写法才是最保险的

2、如何使用位逻辑运算(例如与、或、移位)来实现位向量?(指的是实现位向量的置位,清零,探测的三个操作)

答:

class BitVector{
	private:
		const int shift;
		const int mask;
		const int bitPerWord;
		int *a;

	public:
		const int n;

	public:
		BitVector():shift(5),mask(0x1F),bitPerWord(32),n(10000000)
		{
			a = new int[1+n/bitPerWord];
			for(int i=0;i<n;i++){
				clr(i);
			}
		}
		~BitVector(){
		
		}

		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);
		}
	};
总体来说,这个用一个一维数组标书一个二维数组的方法。首先看输入参数i,这个参数是用来指定到底想要操作哪一位bit的。具体来说,i的第五位确定

某一行的具体哪一个元素,i的高位用来确定是具体哪一行(数组a[]中的哪一个元素,这个int类型的元素有32个bit)。

a[i>>shift]  确定取哪一个数组元素,i>>shift表示取i中的高位来作为数组a的下标</span>
(i&mask)   取i的低五位,在置位,清零,探测操作中,都是先取得低5位的数组(表示具体32bit的哪一位),
置位操作是按位或;清零操作是与非,探测是与

 

  

3、运行时效率是设计目标的一个重要组成部分,所得到的程序需要足够高效。在你自己的系统上实现位图程序并度量其运行时间。该时间与系统排序的运行时间以及习题一种排序的运行时间相比如何??假设n为10 000 000,切输入文件包含1 000 000个整数。

答:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值