Files
CSCI-1200/labs/list_iterators_new
2025-02-12 12:14:10 -05:00
..
2025-02-12 12:14:10 -05:00
2025-02-12 12:14:10 -05:00
2025-02-12 12:14:10 -05:00

Lab 4 — Reversing Data in Different Ways: STL Vectors vs. STL Lists vs. Homemade Linked Lists

Background - Introduction to GIF Formats and the Concept of Frames

What is a GIF?

A GIF (Graphics Interchange Format) is a popular bitmap image format commonly used for its ability to support animations. It was introduced in 1987 by CompuServe and has since become widely used on the internet. GIFs support 256 colors and are often used for simple graphics, icons, or short animations that loop seamlessly. The GIF format is best known for its lightweight nature and ability to be easily shared on social media platforms and websites.

GIF Frames and Animation

A GIF file is made up of a series of frames. Each frame is a static image that, when displayed in sequence, creates the illusion of movement. The concept of frames in a GIF is similar to how traditional film or digital video works, where individual frames are shown at a rapid pace to simulate continuous motion.

Key Concepts:

  • Frames: Each individual image in a GIF sequence. Each frame may display a single static image or a portion of the animation.
  • Frame Duration: Each frame in a GIF has a duration (in milliseconds), determining how long it is displayed before transitioning to the next frame. The timing of each frame is crucial in defining the speed of the animation.
  • Looping: GIFs can be set to loop indefinitely or stop after a certain number of loops. This makes GIFs ideal for short animations that need to play continuously.

Lab Tasks

In this lab, you will modify an existing C++ program. This program reverse a GIF file.

Here are examples of reversing GIF.

Example 1:

Original GIF Reversed GIF

Checkpoint 1A: Reverse with STL Vector Swaps

estimate: TBD

Read the starter code main.cpp and re-write the function reverse that reverses the contents of an STL vector of GIF.

For this checkpoint, use indexing/subscripting/[] on the vector, not iterators (or pointers). You may not use a second vector or array or list. The trick is to step through the vector one location at a time, swapping values between the first half of the vector and the second half. As examples, the value at location 0 and the value at location size()-1 must be swapped, and the value at location 1 and the value at location size()-2 must be swapped. Make sure your code works with even and odd length vectors.

Checkpoint 1B: Reverse with STL List Swaps

estimate: TBD

Copy your code from Checkpoint 1A to a new file. Then, convert this code to use STL Lists instead of STL vectors. Start by replacing vector with list everywhere. And youll need to replace your subscripting with iterators.

You may want to use a straightforward concept we did not discuss in lecture: a reverse iterator. A reverse iterator is designed to step through a list from the back to the front. An example will make the main properties clear:

std::list<int> a;
unsigned int i;
for ( i=1; i<10; ++i ){
	a.push_back( i*i );
}
std::list<int>::reverse_iterator ri;
for( ri = a.rbegin(); ri != a.rend(); ++ri ){
	std::cout << *ri << std::endl;
}

This code will print out the values 81, 64, 49, . . . , 1, in order, on separate lines. You can also compile and run this example program.

Observe the type for the reverse iterator, the use of the functions rbegin and rend to provide iterators that delimit the bounds on the reverse iterator, and the use of the ++ operator to take one step backwards through the list. It is very important to realize that rbegin and end are NOT the same thing! One of the challenges here will be determining when to stop (when youve reached the halfway point in the list). You may use an integer counter variable to help you do this.

For this checkpoint you should not use erase, or insert, or the push or pop functions. Note, youll probably need to add the keyword typename in front of your templated iterator types to unconfuse the compiler.

typename std::list<T>::iterator itr = data.begin();

To complete this checkpoint, show a TA your debugged functions to reverse STL vectors and STL lists by element swapping. Be sure to ask your TA/mentors any questions you have about regular vs. reverse iterators for lists and vectors.

Checkpoint 2: Reverse with STL List Using Insert/Erase/Push/Pop

estimate: TBD

Form a team of 4. You may form a team of 2 or 3 only with approval from your graduate lab TA.

Each student should make a copy of their solution file for Checkpoint 1B. And then, each student should rewrite their STL list reverse function:

  • STUDENT 1 Using only front(), pop_front(), and insert().
  • STUDENT 2 Using only back(), pop_back(), insert(), and iterator increment.
  • STUDENT 3 Using only erase(), push_front(), and iterator dereference.
  • STUDENT 4 Using only erase(), push_back(), iterator dereference, and iterator decrement.
    Each of these solutions is allowed to use a for or while loop and a temporary variable to store a single element, but should not use any auxiliary data structures (no array, no vector, no additional list, etc.)

Note that these solutions are quite different than the algorithms that reverse a vector or list by swapping values. If the algorithm is paused and printed midway, the vector contents will be different than the algorithms for Checkpoint 1. (Go ahead, add more calls to the print function in the middle of your reverse function.) Test and debug your own code before helping your teammates. Discuss the similarities and differences between the solutions to each version of the reverse function.

To complete this checkpoint, as a team, present your debugged solutions to a TA or mentor.

Checkpoint 3: Reversing a Homemade Linked List

estimate: TBD

This checkpoint is an individual checkpoint. (But you can ask your teammates questions if you get stuck.) Pull out some paper. Following the conventions from lecture, draw a picture of a “homemade” singly-linked list that stores the values 1, 2, 3, and 4. Make a variable on the stack named my_list of type Node* that points to the first node in the chain (the node storing the value 1). The 4 node objects should be separate blobs of memory dynamically-allocated on the heap.

Now, modify this diagram to reverse the list you can do this by only changing pointers! You should use the existing node objects. Dont copy the entire diagram or make any new nodes. You should not change the values inside of any node dont swap values like we did for Checkpoint 1. Then, write pseudo-code to reverse this list, just changing the pointers as you diagrammed above. You may use helper variables (of type Node*) but no other data structures or variables. Remember that when we directly manipulate homemade linked lists we dont use iterators.

Finally, read the starter code of checkpoint 3: checkpoint3.cpp. Complete the reverse function using your diagram and pseudocode as a guide. Test and debug the code. Add a few additional test cases to the main function to ensure your code works with an empty list, and lists with one or two values. Also add a test or two of a node chain with something other than ints. If you have time, write 2 versions of this function, one version should be iterative (using a for or while loop) and one version should be recursive.

Note: this reverse function takes a pointer as its argument, but we are passing this pointer by reference, because we want to modify this pointer. To understand the concept of passing a pointer by reference, you are recommended to read and run this example program.

To complete this checkpoint, show a TA or mentor your diagram and your debugged function(s) to reverse a homemade singly-linked list.