现在的位置: 首页 > 综合 > 正文

编程珠玑_第十三章_生成一个随机整数的有序集合

2019年03月20日 ⁄ 综合 ⁄ 共 2461字 ⁄ 字号 评论关闭

 题目:生成一个随机整数的有序集合

 

1 线性结构

数组  链表

2 二分搜索树

3 位向量

#include <iostream>

using namespace std;

enum {BITSPERWORD=32,SHIFT=5,MASK=0x1F};
class IntSetBitVec
{
public:
	IntSetBitVec(int maxelements,int maxval);
	void report(int *v);
	void insert(int t);
	int NumOfElements() {return n;}
private:
	int n,hi,*x;
	void set(int i) {       x[i>>SHIFT] |= (1<<(i&MASK));}
	void clr(int i) {       x[i>>SHIFT] &=~(1<<(i&MASK));}
	int test(int i) {return x[i>>SHIFT] &  (1<<(i&MASK)); }
};
IntSetBitVec::IntSetBitVec(int maxelements, int maxval)
{
	n=0;
	hi=maxval;
	x=new int[1+hi/BITSPERWORD];
	for(int i=0;i<=hi;i++)
		clr(i);
}
void IntSetBitVec::report(int *v)
{
	int j=0;
	for(int i=0;i<=hi;i++)
		if (test(i))
			v[j++]=i;
}

void IntSetBitVec::insert(int t)
{
	if (test(t))
	{
		return;
	}
	set(t);
	n++;
}

void GenSet(int m,int maxval)
{
	int *v=new int[m];
	IntSetBitVec intSet(m,maxval);
	while (intSet.NumOfElements()<m)
		intSet.insert(rand()%maxval);
	intSet.report(v);
	for (int i=0;i<m;i++)
	{
		cout<<v[i]<<" ";
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	GenSet(500,10000);
	return 0;
}

 

4  箱

#include <iostream>
using namespace std;
struct node
{
	int val;
	node* next;
	node(int v,node* p){val=v;next=p;}
};
class IntSetBins
{
public:
	IntSetBins(int maxelement,int pmaxval);
	void insert(int t);
	void report(int* v);
	int NumOfElements() {return n;}

private:
	node* rinsert(node* p,int t);
	int n,bins,maxval;
	
	node **bin,*sentinel;//sentinel 哨兵

};



IntSetBins::IntSetBins(int maxelement,int pmaxval)
{
	bins=maxelement;
	maxval=pmaxval;
	bin=new node*[bins];
	sentinel=new node(maxval,0);
	for (int i=0;i<bins;i++)
	{
		bin[i]=sentinel;
	}
	n=0;
}

node* IntSetBins::rinsert(node* p,int t)
{
	if (p->val<t)
	{
		p->next=rinsert(p->next,t);
	}
	else if (p->val>t)
	{
		p=new node(t,p);
		n++;
	}
	return p;
}
void IntSetBins::insert(int t)
{
	int i=t/(1+maxval/bins);
	bin[i]=rinsert(bin[i],t);

}

void GenSet(int m,int maxval)
{
	int *v=new int[m];
	IntSetBins intSet(m,maxval);
	while (intSet.NumOfElements()<m)
		intSet.insert(rand()%maxval);
	intSet.report(v);
	for (int i=0;i<m;i++)
	{
		cout<<v[i]<<" ";
	}
}

void IntSetBins::report(int* v)
{
	int j=0;
	for(int i=0;i<bins;i++)
		for (node* p=bin[i];p!=sentinel;p=p->next)
		{
			v[j++]=p->val;
		}

}


int _tmain(int argc, _TCHAR* argv[])
{
	GenSet(100,10000);
	return 0;
}


5 上面这些数据结构和算法的平均性能如下

 

集合表示    初始化     insert      report       总时间       空间

数组                1               m             m         O(m*m)        m

链表                1               m             m         O(m*m)        2m

二叉树            1               logm        m       O(mlogm       3m

箱                    m               1              m         O(m)              3m

位相量             n                1               n           O(n)              n/b

 

将递归函数重写为迭代器版本可以使链表的速度提升为原来的3倍,但只能使箱提速10%.对于大多数数据结构来说,引入哨兵可以获得清晰、简单的代码,并缩短运行时间。

抱歉!评论已关闭.