Lecture 6: ALists, Resizing, vs. SLists

9/9/2020

A Last Look at Linked Lists

Doubly Linked Lists

Arbitrary Retrieval

Naive Array Lists

Random Access in Arrays

Our Goal: AList.java

public class AList { private int[] items; private int size; /** Creates an empty list. */ public AList() { items = new int[100]; size = 0; } /** Inserts X into the back of the list */ public void addLast(int x) { items[size] = x; size = size + 1; } /** Returns the item from the back of the list. */ public int getLast() { return items[size-1]; } /** Gets the ith item from the List (0 is the front) */ public int get(int i) { return items[i]; } /** Returns the number of items in the list. */ public int size() { return size; } }

Naive AList Code

The Abstract vs. the Concrete

Deletion

public class AList { private int[] items; private int size; /** Creates an empty list. */ public AList() { items = new int[100]; size = 0; } /** Inserts X into the back of the list */ public void addLast(int x) { items[size] = x; size = size + 1; } /** Returns the item from the back of the list. */ public int getLast() { return items[size-1]; } /** Gets the ith item from the List (0 is the front) */ public int get(int i) { return items[i]; } /** Returns the number of items in the list. */ public int size() { return size; } /** Deletes item from back of the list and returns deleted item */ public int removeLast() { int x = getLast(); items[size-1] = 0; // Not necessary to preserve invariants -> not necessary for correctness size = size - 1; return x; } }

Resizing Arrays

The Mighty AList

Array Resizing

Implementation

public class AList { private int[] items; private int size; /** Creates an empty list. */ public AList() { items = new int[100]; size = 0; } /** Resizes the underlying array to the target capacity */ private void resize(int capacity) { int[] a = new int[capacity] System.arraycopy(items, 0, a, 0, size); items = a; } /** Inserts X into the back of the list */ public void addLast(int x) { if (size == items.length) { resize(size + 1); } items[size] = x; size = size + 1; } /** Returns the item from the back of the list. */ public int getLast() { return items[size-1]; } /** Gets the ith item from the List (0 is the front) */ public int get(int i) { return items[i]; } /** Returns the number of items in the list. */ public int size() { return size; } /** Deletes item from back of the list and returns deleted item */ public int removeLast() { int x = getLast(); items[size-1] = 0; // Not necessary to preserve invariants -> not necessary for correctness size = size - 1; return x; } }

Basic Resizing Analysis

Runtime and Space Usage Analysis

Array Resizing

Runtime and Space Usage Analysis

Resizing Slowness

Making AList Fast

Fixing the Resizing Performance Bug

public class AList { private int[] items; private int size; /** Creates an empty list. */ public AList() { items = new int[100]; size = 0; } /** Resizes the underlying array to the target capacity */ private void resize(int capacity) { int[] a = new int[capacity] System.arraycopy(items, 0, a, 0, size); items = a; } /** Inserts X into the back of the list */ public void addLast(int x) { if (size == items.length) { resize(size * 2); // A subtle fix!!! } items[size] = x; size = size + 1; } /** Returns the item from the back of the list. */ public int getLast() { return items[size-1]; } /** Gets the ith item from the List (0 is the front) */ public int get(int i) { return items[i]; } /** Returns the number of items in the list. */ public int size() { return size; } /** Deletes item from back of the list and returns deleted item */ public int removeLast() { int x = getLast(); items[size-1] = 0; // Not necessary to preserve invariants -> not necessary for correctness size = size - 1; return x; } }

(Probably) Surprising Fact

public void addLast(int x) { if (size == items.length) { resize(size * 2); // A subtle fix!!! } items[size] = x; size = size + 1; }

Performance Problem #2

Memory Efficiency

Generic AList

There's a Problem

public class AList<Item> { private Item[] items; private int size; /** Creates an empty list. */ public AList() { items = (Item[]) new Object[100]; size = 0; } /** Resizes the underlying array to the target capacity */ private void resize(int capacity) { Item[] a = (Item[]) new Object[capacity] System.arraycopy(items, 0, a, 0, size); items = a; } /** Inserts X into the back of the list */ public void addLast(int x) { if (size == items.length) { resize(size * 2); // A subtle fix!!! } items[size] = x; size = size + 1; } /** Returns the item from the back of the list. */ public Item getLast() { return items[size-1]; } /** Gets the ith item from the List (0 is the front) */ public Item get(int i) { return items[i]; } /** Returns the number of items in the list. */ public int size() { return size; } /** Deletes item from back of the list and returns deleted item */ public Item removeLast() { int x = getLast(); items[size-1] = null; size = size - 1; return x; } }

Generic ALists (similar to generic SLists)

Nulling Out Deleted Items