Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Data Structure and Algorithms - Assignment 2 Questions | CS 245, Assignments of Data Structures and Algorithms

Material Type: Assignment; Class: Data Struct & Algorithms; Subject: Computer Science; University: University of San Francisco (CA); Term: Spring 2005;

Typology: Assignments

Pre 2010

Uploaded on 07/30/2009

koofers-user-pwo
koofers-user-pwo 🇺🇸

3

(1)

10 documents

1 / 7

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Department of Computer Science University of San Francisco
Computer Science 245
Programming Assignment 2
Spring 2005
1 Introduction
Recall that the heap is the memory used by the system to service requests for memory made by
the new operation in Java. Also recall that memory that has been allocated from the heap that
is no longer being used by the program is periodically returned to the heap by the Java garbage
collector. In languages such as C and C++ memory allocated from the heap that is no longer in
use should be explicitly returned to the heap by the program. In programming assignment 2 we’ll
look at how one might write software for explicitly allocating and deallocating from the heap.
One approach involves the use of a linked list that’s stored in the heap: each available block of
contiguous memory stores two pieces of information: its size and the address of the next available
block of memory. If the address of the first block is also stored, then the sequence of available
blocks forms a linked list.
For example, suppose the heap consists of 16 memory locations, and addresses 2, 3, 6, 7, and
10–15 are free. Then, together with the address 2 the address of the first free block our
“linked list” might look something like this:
Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Contents X X 6 2 X X 10 2 X X -1 6
In this diagram, memory that has been allocated (addresses 0, 1, 4, 5, 8, and 9) is marked with an
‘X’, and the first two addresses in each free block store the address of the next free location and
the size of the free block, respectively. So address 2 stores 6, since address 6 is the beginning of
the next free block, and address 3 stores 2 since the first free block has 2 elements. Note that the
first location in the last free block (location 10) stores a -1. In our examples we’re using this value
to indicate that there are no more blocks of free storage.
When a program makes a request for memory, the system can traverse the linked list of free
blocks until it finds one that’s big enough to satisfy the new request. In our example, if a request
is made for 4 locations, the memory management software would start with the first free block
(address 2), see that it only has 2 locations available, continue to the block starting at address 6,
see that it also only has 2 locations available, and, finally, see that the block starting at address 10
with 6 locations is big enough to satisfy the request.
In order to satisfy the request, the system simply reduces the size of the block starting at
location 10 by four and returns the address 12:
Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Contents X X 6 2 X X 10 2 X X -1 2 X X X X
Notice that in our example we’re allocating memory from the end of the block.
Things get more complicated if a request is made for an entire block. For example, if a program
requests 2 locations, the entire block starting in location 2 can be used, and the address of the first
free block will have to be changed to 6:
1
pf3
pf4
pf5

Partial preview of the text

Download Data Structure and Algorithms - Assignment 2 Questions | CS 245 and more Assignments Data Structures and Algorithms in PDF only on Docsity!

Department of Computer Science University of San Francisco

Computer Science 245

Programming Assignment 2

Spring 2005

1 Introduction

Recall that the heap is the memory used by the system to service requests for memory made by the new operation in Java. Also recall that memory that has been allocated from the heap that is no longer being used by the program is periodically returned to the heap by the Java garbage collector. In languages such as C and C++ memory allocated from the heap that is no longer in use should be explicitly returned to the heap by the program. In programming assignment 2 we’ll look at how one might write software for explicitly allocating and deallocating from the heap. One approach involves the use of a linked list that’s stored in the heap: each available block of contiguous memory stores two pieces of information: its size and the address of the next available block of memory. If the address of the first block is also stored, then the sequence of available blocks forms a linked list. For example, suppose the heap consists of 16 memory locations, and addresses 2, 3, 6, 7, and 10–15 are free. Then, together with the address 2 — the address of the first free block — our “linked list” might look something like this:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents X X 6 2 X X 10 2 X X -1 6

In this diagram, memory that has been allocated (addresses 0, 1, 4, 5, 8, and 9) is marked with an ‘X’, and the first two addresses in each free block store the address of the next free location and the size of the free block, respectively. So address 2 stores 6, since address 6 is the beginning of the next free block, and address 3 stores 2 since the first free block has 2 elements. Note that the first location in the last free block (location 10) stores a -1. In our examples we’re using this value to indicate that there are no more blocks of free storage. When a program makes a request for memory, the system can traverse the linked list of free blocks until it finds one that’s big enough to satisfy the new request. In our example, if a request is made for 4 locations, the memory management software would start with the first free block (address 2), see that it only has 2 locations available, continue to the block starting at address 6, see that it also only has 2 locations available, and, finally, see that the block starting at address 10 with 6 locations is big enough to satisfy the request. In order to satisfy the request, the system simply reduces the size of the block starting at location 10 by four and returns the address 12:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents X X 6 2 X X 10 2 X X -1 2 X X X X

Notice that in our example we’re allocating memory from the end of the block. Things get more complicated if a request is made for an entire block. For example, if a program requests 2 locations, the entire block starting in location 2 can be used, and the address of the first free block will have to be changed to 6:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents X X X X X X 10 2 X X -1 2 X X X X In general, if an entire block is requested, the address stored in the preceding free block will have to be changed. For example, suppose the heap looks like this (e.g., addresses 4–5 and 0– have been freed):

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 4 2 X X 10 4 X X -1 2 X X X X

If a request is now made for a block of size 4, the entire block starting at address 4 will be allocated, and the address stored in 0 will have to be changed to 10:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 10 2 X X X X X X X X -1 2 X X X X When memory is freed, a new block is “inserted” into the linked list. For example, if a block of size 2 starting at address 6 is freed, then the updated memory should look like this:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 6 2 X X X X 10 2 X X -1 2 X X X X

Notice that the address stored in the free block at 0, the immediately preceding block, is updated to reference the new block, and the address in the newly freed block is the old address stored in the immediately preceding block at address 0. In general, when a block is freed, simply “inserting” it in the linked list won’t be enough. For example, if a block of size 2 starting at address 4 is now freed, and simply inserted into the list, we’ll have the following layout:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 4 2 X X 6 2 10 2 X X -1 2 X X X X

The problem here is that all the blocks have size 2, and a request for a block of size 4 will be (incorrectly) refused. So after a freed block is inserted into the list, the system should see if it can be merged with the following or preceding blocks (or both). In our example, a correct freeing of the block at address 4 will continue by merging the block at 4 and the block at 6:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 4 2 X X 10 4 X X -1 2 X X X X

If we free a block of size 2 at address 12, we should first create a new block:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 4 2 X X 10 4 X X 10 2 -1 2 X X

and then merge the block at 10 and the block at 12:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 4 2 X X 10 4 X X -1 4 X X

Finally, if we free the block of size 2 at address 2, we should first insert the new block:

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 2 2 4 2 10 4 X X -1 4 X X

3 Errors

It is possible that the user will request a block of memory larger than any available block, in which case your allocate method should return the constant NO ADDRESS. However, you may assume that the user will not try to free memory that hasn’t been allocated. You also don’t need to check whether a freed block contains memory that belongs to another free block. If the user enters an invalid command, the program should just prompt for a correct command and continue.

4 Design Issues

The header of a block in the free list is the two ints consisting of the address of the next block and the size of the block. It is important that there be enough room for this header in any block of memory in the free list. So any block of memory in the free list must be capable of storing at least two ints. It might at first seem that this could be dealt with by simply insisting that the user always allocate blocks of size at least two. However, this isn’t enough. For example, suppose the user requests a block of size 7 when memory has the following configuration.

Address 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Contents 10 8 X X -1 4 X X

If any request of size at least two is allowed, then the block starting at address 1 will be allocated, leaving a free block of size 1 at address 0, and we can’t store both the address of the next block and the size of the block. The solution is simple, though. Just make sure that any operation on memory — an allocate or release — operates on a block that is a multiple of the header size. In our examples, the header size is 2. So you could simply add the following code to the beginning of the allocate and release methods:

if (size % 2 != 0) size++;

A somewhat more robust approach allows for the possibility that the block header might change (e.g., if we wanted a doubly linked free list):

int addon = (HEADER_SIZE - (size % HEADER_SIZE)) % HEADER_SIZE; size = size + addon;

Here HEADER SIZE is a final member of the Memory class. In this connection note that it’s essential that the size of the memory allocated by the constructor also be a multiple of the header size. There are many possible approaches to the design of the allocate and release methods. Here’s the design I used:

// allocate Make sure the size is a multiple of the header size. Search for a block containing at least the desired memory. If a block was found { Compute the address of the block to be returned. Update the size of the block being used to service the request. If the new block size is zero Adjust the links in the free list. }

return the address of the block or NO_ADDRESS

// release Make sure the size is a multiple of the header size. If all memory is being used { Create a new block with the freed block. Update the address of the first free block. } else if the address of the first free block is greater than the address of the freed block { Create a new block with the freed block. Update the address of the first free block. Update the free list by merging blocks as necessary. } else { // freed block follows first block Find the immediate predecessor of the block being freed. Create a new block with the freed block. Update the next block address in the immediate predecessor of the freed block. Merge the new block and the following block as necessary. Merge the new block and its immediate predecessor as necessary. }

You do not have to use these designs. To the contrary, I encourage you to look for more efficient approaches. For example, as I described it, the allocate method searches for the first block that’s big enough to satisfy the request, and it might be better to look instead for a block that fits the request as closely as possible. For example, if there’s a request for a block of size 4, and there are free blocks of sizes 8 and 4, in this order, then the algorithm I used would return half of the block of size 8. This will leave two blocks of size 4, and a subsequent request for a block of size 8 will fail. If the algorithm returned the second block, the block of size 4, a subsequent request for a block of size 8 could be fulfilled.

5 Extra Credit

You can get up to 10 points extra credit by using your class to implement a multiset of ints with a linked list. A multiset is like a set, except that it allows duplicates. For example, the set { 1 , 2 , 2 , 3 } is the same as the set { 1 , 2 , 3 }, but the multiset { 1 , 2 , 2 , 3 } is different from the multiset { 1 , 2 , 3 }. The operations you should implement are

  1. boolean member(int val): return true if val belongs to the multiset, false otherwise.
  2. void insert(int val): add val to the multiset (regardless of whether it’s already in the multiset). You can just insert at the beginning of the list.
  3. void remove(int val): remove the first occurrence of val from the multiset.
  4. void print(): print the contents of the multiset (in the order in which the data is stored in the linked list).
  5. boolean isEmpty(): return true if the multiset is empty; return false otherwise.

7 Due Date

In order to receive full credit, your program must be submitted electronically by 3:00 pm on Wednesday, March 2nd, and you must turn in printouts of your source files by 6 pm on the 2nd. You can receive half credit if you submit your program and turn in a print out after 3:00 pm Wednesday but before 3:00 pm Thursday. Programs submitted later than 3:00 pm Thursday, March 3, will receive no credit.

8 Grading

Correctness will be 60% of your grade. Does your program correctly allocate, release, and print the contents of the free list? Does it correctly handle requests for unavailable memory? The following static features will be graded.

  1. Documentation will be 10% of your grade. Does your header documentation include the author’s name, the purpose of the program, and a description of how to use the program? Are the identifiers meaningful? Are any obscure constructs clearly explained? Does the method header documentation explain the purpose of the method, its arguments, and its return value?
  2. Source format will be 10% of your grade. Is the indentation and naming of identifiers consis- tent? Have blank lines been used so that the program is easy to read? Are there any lines of source that are longer than 80 characters?
  3. Quality of solution will be 20% of your grade. Did you use the required class? Are any of your methods more than 40 lines? Are there long or multipurpose methods? Is your solution too clever — i.e., has the solution been condensed to the point where it’s incomprehensible?

9 Collaboration

It is OK for you to discuss solutions to this program with your classmates. However, no collaboration should ever involve looking at one of your classmate’s source programs! It is usually extremely easy to determine that someone has copied a program, even when the indivdual doing the copying has changed identifiers and comments. If we discover that someone has copied a program, the authors of both programs will receive an F in the course. Repeat offenders will be referred to the Academic Honesty Committee for additional disciplinary action.