The goal of this lab is to practice using bit operations; in this case, we will use an ordered collection of bits to represent a dynamic set.
A few weeks ago we talked briefly about the dictionary
data structure, the most familiar implementation of which is
Java's HashMap
.
A similar data structure is the dynamic set, as implemented by
Java's HashSet
.
A dynamic set is an unordered collection of uniform-typed items with
the operations
(It is worth pointing out what's dynamic about a dynamic set.
In the mathematical concept of set, a set cannot change.
If you have a set, say A = { 1, 4, 5}
,
and union to it, say B = {2, 4, 6}
,
you produce a new set, call it C = {1, 2, 4, 5, 6}
;
you do no make any change to the set A,
just as adding 7 to 5 makes 12--- it doesn't change "5".
A dynamic set, on the other hand, is a mutable data structure.)
Some applications of dynamic sets require a few other additional operations like the operations on mathematical sets:
Bit operations can be used to make a very fast and space-efficient implementation of a dynamic set, but only under limited circumstances:
For our purposes today, we will assume we want to work with
subsets of the set {0, 1, 2, ...
n}.
The main idea is simple. For each dynamic set we keep a sequence of bits numbered from 0 to n. If the ith bit is set to true or 1, that indicates that i is in the set; false or 0 indicates that it is not.
Conceptually we want an array of bits, or as it is traditionally called,
a bit vector.
We can't literally use a traditional array because we don't have addresses
for a single bit.
We could make an array of, say, char
s and use only one
bit from each array location, but that would use 8 times as much memory as
we really need.
Instead, we will employ the bit manipulation operations we learned in class
on Monday to implement a bit vector, which will then be used to implement
a dynamic set.