搜索
问题:生成[0, maxval]范围内m个随机整数的有序序列
1.有序数组
时间:O(m^2) 空间:m
class IntSetArray
{
private:
int n;
int *x;
public:
IntSetArray(int maxelements, int maxval)
{
x = new int[1 + maxelements];
n = 0;
x[0] = maxval;
}
int size()
{
return n;
}
//采用直接插入,按照升序插入数据
void insert(int t)
{
int i;
for (i = 0; x[i] < t; i++) ;
if (x[i] == t)
return;
for (int j = n; j >= i; j--)
x[j + 1] = x[j];
x[i] = t;
n++;
}
void report(int *v)
{
for (int i = 0; i < n; i++)
v[i] = x[i];
}
};
调用:
void randArray(int m, int n)
{
int *x = new int[n];
IntSetArray arr(m , n);
while (arr.size() < m)
arr.insert(bigRand() % n);
arr.report(x);
}
2.有序链表
时间:O(m^2) 空间:2m
如果实现不知道集合大小,使用链表,哨兵节点
class IntSetList
{
private:
int n;
struct node
{
Int val;
node *next;
node(int v, node *p)
{
val = v;
next = p;
}
};
node *head, *sentinel;
node *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;
}
public:
IntSetList(int maxelements, int maxval)
{
sentinel = head = new node(maxval, 0);
n = 0;
}
int size()
{
return n;
}
void insert(int t)
{
head = rinsert(head, t);
}
void report(int *v)
{
int j = 0;
for (node *p = head; p != sentinel; p = p->next)
v[j++] = p->val;
}
};
3.二叉树
时间:O(mlogm) 空间:3m
class IntSetBST
{
private:
int n, *v, vn;
struct node
{
int val;
node *left, *right;
node(int v)
{
val = v;
left = right = 0;
}
};
node *root;
node *rinsert(node *p, int t)
{
if (p == 0)
{
p = new node(t);
n++;
}
else if (t < p->val){
p->left = rinsert(p->left, t);
}
else if (t > p->val){
p->right = rinsert(p->right, t);
}
else
; // do nothing if p->val == t
return p;
}
//中序遍历
void traverse(node *p)
{
if (p == 0)
return;
traverse(p->left);
v[vn++] = p->val;
traverse(p->right);
}
public:
IntSetBST(int maxelems, int maxval)
{
root = 0;
n = 0;
}
int size()
{
return n;
}
void insert(int t)
{
root = rinsert(root, t);
}
void report(int *x)
{
v = x;
vn = 0;
traverse(root);
}
};
4.箱
时间:O(m) 空间:3m
结合数据结构和位向量的有点
class IntSetBins
{
private:
int n, bins, maxval;
struct node{
int val;
node *next;
node(int v, node *p)
{
val = v;
next = p;
}
};
node **bin, *sentinel;
node *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++;
}
else
;
return p;
}
public:
IntSetBins(int maxelems, int maxval)
{
bins = maxelems;
this->maxval = maxval;
bin = new node*[bins];
sentinel = new node(maxval, 0);
for (int i = 0; i < bins; i++)
{
bin[i] = sentinel;
}
n = 0;
}
int size()
{
return n;
}
void insert(int t)
{
int i = t / (1 + maxval / bins);
bin[i] = rinsert(bin[i], t);
}
void 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;
}
}
};
5.位向量
时间:O(n) 空间:n/b
class IntSetBitVec
{
private:
enum{
BITSPERWORD = 32,
SHIFT = 5,
MASK = 0x1F
};
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));
}
public:
IntSetBitVec(int maxelems, int maxval)
{
hi = maxval;
x = new int[1 + hi / BITSPERWORD];
for (int i = 0; i < hi; i++)
{
clr(i);
}
n = 0;
}
int size()
{
return n;
}
void insert(int t)
{
if (test(t))
return;
set(t);
n++;
}
void report(int *v)
{
int j = 0;
for (int i = 0; i < hi; i++)
if (test(i))
v[j++] = i;
}
};
库的作用,空间的重要性
代码调优:最显著的改进就是用只分配一个较大的内存块的方案来替换通用内存分配。这就消除了很多开销较大的调用。对于大多数结构来说,引入哨兵可以获得清晰简单的代码,并缩短运行时间。