Lecture Notes for SE 598, Data Structures and Algorithms
12 July 2000, List Applications
- heap storage management
- dynamic storage -
new()
and (usually) free()
- dynamically managed storage comes from a big block of storage called
the heap
- each call to
new()
chips off a piece of storage of the proper size
from the heap
- calls to
free()
return a piece of storage back to the heap
-
new()
and free()
calls may occur in any order
- heaps tend to become fragmented with gaps of allocated but not yet
freed storage
- lists are a useful data structure for implementing heaps
- can expand and shrink to keep up with the heap size
- can delete (
new()
) and insert (free()
) new entries anywhere
in the list
- each allocated piece has a header to keep track of its location in
the heap
-
struct header {
char * block;
unsigned size;
};
- the heap itself is a list of headers
-
typedef list
- to allocate a block
new(size)
- find a piece big enough to fill the request
-
Heap::iterator i;
for (i = hp.begin(); i != hp.end(); i++)
if ((*i).size >= size) break;
- if no such piece exists, return 0; otherwise carve off a piece
-
if (i == hp.end())
return 0;
char * b = (*i).block;
(*i).block += size;
(*i).size -= size;
- if the left-over piece is empty, delete it
-
if ((*i).size == 0)
hp.erase(i);
- to free an allocated block
free(b)
- find out where the block fits in the list and insert it
-
Heap::iterator i;
for (i = hp.begin(); i != hp.end(); i++)
if (b.block < (*i).block) break;
i = hp.insert(i, b);
- coalesce adjacent blocks into a single, bigger block
-
if (i != hp.begin()) {
Heap::iterator previous = i;
previous--;
if ((*previous).block + (*previous).size == (*i).block) {
(*previous).size += (*i).size;
hp.erase(i);
i = previous;
}
}
Heap::iterator next = i;
next++;
if (next != hp.end())
if ((*i).block + (*i).size == (*next).block) {
(*i).size += (*next).size;
hp.erase(next);
}
- sparse matrices
- matrices are a useful way to model the world
- schedules - class schedules, train schedules
- real-world matrix models are often huge - 100,000 on a side
- but, real-world matrix models are often sparse
- a vast majority of the matrix elements contain the same value
- consider the train schedule
- a sparse-matrix representation encodes only the non-common values,
saving vast amounts of space
- a list containing the columns of the sparse matrix
- each column is a list containing the values in the rows for that column
-
template <typename T>
class sparse_matrix {
private:
template <typename CellT>
struct Cell {
int coord;
CellT value;
};
typedef list<Cell<T> > column;
typedef list<Cell<column> > columns;
columns sm;
};
- each sparse matrix has a default value representing the majority value
-
sparse_matrix(T & default);
- to read a value, return the value if it exists, otherwise return the
default value
- to write a value, make sure the corresponding cell exists, then store
the value
This page last modified on 11 July 2000.