Basic Data Structures

My Take on UCSD's Basic Data Structures course (CSE 12)


Project maintained by nate-browne Hosted on GitHub Pages — Theme by mattgraham

ArrayLists and Vectors

Chapter 3 of Data Structures and Algorithm Analysis in C++

arraylist

The Motivation

Arrays are great.

int[] array = {1,2,3,5,7,11};
int array[] = {1,2,3,5,7,11};

Note: C++ arrays don’t know their own length (unlike in Java) so this makes them a bit more annoying to use… The C and C++ libraries deal with this by either having a null value inserted at the end to know when it is reached, or they will pass in the length as another argument.

Arrays aren’t great?

Let’s fix (some of) these problems!

First, resizing. Any ideas for solutions?

Let’s build our own, implementing some basic features. Our array will only hold integers for now.

(I’m about to introduce C++ classes right now; don’t panic)

class MyArray {
 private:
  int *arr; // The array itself
  int size; // Size of the array
  int num_elements; // Number of elements
 public:
  // Default constructor.
  MyArray(void) {
    this->size = 10;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

  // Constructor that takes the size to make the array
  MyArray(int size) {
    this->size = size;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

A Quick Aside: C++ Classes

Next up: How should we implement insert?

Enhancing our class: Insertion

class MyArray {
 private:
  int *arr; // The array itself
  int size; // Size of the array
  int num_elements; // Number of elements
 public:
  // Default constructor.
  MyArray(void) {
    this->size = 10;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

  // Constructor that takes the size to make the array
  MyArray(int size) {
    this->size = size;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

  void add(int element) {
    this->arr[this->num_elements] = element;
    ++this->num_elements;
  }

Easy enough. Now, resizing. How should we do this?

class MyArray {
 private:
  int *arr; // The array itself
  int size; // Size of the array
  int num_elements; // Number of elements

  void resize(void) {
    this->size = this->size * 2 + 1;
    int *temp_arr = new int[this->size];
    int index = 0;

    while(index <= this->num_elements) {
      temp_arr[index] = this->arr[index];
      index++;
    }

    delete [] this->arr;
    this->arr = temp_arr;
  }

 public:
  // Default constructor.
  MyArray(void) {
    this->size = 10;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

  // Constructor that takes the size to make the array
  MyArray(int size) {
    this->size = size;
    this->arr = new int[this->size];
    this->num_elements = 0;
  }

  ~MyArray(void) {
    delete [] this->arr;
  }

  void add(int element) {
    if(this->num_elements == this->size) {
      this->resize();
    }
    this->arr[this->num_elements] = element;
    ++this->num_elements;
  }

You’ll have to implement delete yourself ;)

The data structure we’ve implemented has a name: the ArrayList (Java)/Vector (C++)

Another Sidenote: ADTs vs Data Structures

In this class, we’ll (mostly) discuss Abstract Data Types (ADTs)

A data structure is an implementation.

Think of ADTs as an interface, and data structures as a class.

Example data structures:

Example Abstract Data Types:

Now back to the main content.

ArrayLists/Vectors

What’s the runtime of…

size?

empty?

operator[]/at and front and back?

pop_back?

insert?

push_back?

To fully understand the runtime of push_back, wait until an advanced algorithms class where amortization is discussed. We won’t cover that now :), but you can read about it in chapter 11!

When should we use a Vector versus an array?

Use an array when…

  1. You know the exact number of elements that will be inserted ever or want to limit the number
  2. You’re writing C++ that may be called from/used by some C code.
  3. You have limited memory.
  4. You’ll have way more accesses than insertions/removals.

Use a vector when…

  1. You will be doing a lot of insertions/removals.
  2. You don’t know how much you’ll be holding/you want an “unlimited” container.
  3. You want to implement another ADT that also shouldn’t have a maximum size.

To summarize, you’ll probably end up using vectors a lot.

That’s all folks! Next time: Stacks and Queues.

back