ADS-Lecture 05 DLLs and Arrays

Lecture 05 DLLs and Arrays

Doubly Linked Lists (In Brief)

Draw box and pointer notation on paper if you find this part a bit hard to understand.

One Downside of SLLists

Inserting at the back of an SLList is much slower than the front.

public void addFirst(int x) {
  size += 1;
  sentinel.next = new IntNode(x, sentinel.next);
} 
public void addLast(int x) {
   size += 1;
   IntNode p = sentinel;
   while (p.next != null) {
       p = p.next;
   }
   p.next = new IntNode(x, null);
}
Improvement #7: .last and .prev

We added .last. What other changes might we make so that remove is also fast?

  • Add backwards links from every node.

  • This yields a “doubly linked list” or DLList, as opposed to our earlier “singly linked list” or SLList.

Doubly Linked Lists

A Naive Version

Reverse pointers allow all operations (add, get, remove) to be fast.

  • We call such a list a “doubly linked list” or DLList.

Non-obvious fact: This approach has an annoying special case: last sometimes points at the sentinel, and sometimes points at a ‘real’ node.

Improve: Double Sentinel Version

One solution: Have two sentinels.

Improve: Circular Sentinel Version

Even better topology (IMO) :

Use one sentinel as both the front and last sentinel, creating a circle.

Improvement #8: Fancier Sentinel Node(s)

While fast, adding .last and .prev introduces lots of special cases.

To avoid these, either:

  • Add an additional sentBack sentinel at the end of the list.
  • Make your linked list circular , with a single sentinel in the middle.
DLList Summary
MethodsNon-Obvious Improvements
addFirst(int x)Rebranching: IntList -> IntNode
getFirst()Bureaucracy: SLList
size()Access Control: public -> private
addLast(int x)Nested Class: Bringring IntNode into SLList
removeLast()Caching: Saving size as an int.
Generalizing: Adding a sentinel node to allow representation of the empty list.
Looking back: .last and .prev allow fast removeLast
Sentinel upgrade: Avoiding special cases with sentBack or circular list

Generic Lists

One issue with our list classes: They only supports integers.

SLists

Java allows us to defer type selection until declaration.

public class SLList<BleepBlorp> {
   private IntNode sentinel;
   private int size;
   
   public class IntNode {
      public BleepBlorp item;
      public IntNode next;
      ...   
   }
   ...
}
SLList<Integer> s1 = new SLList<>(5);
s1.addFirst=(10);
 
SLList<String> s2 = new SLList<>("hi");
s2.addFirst("apple");
Generics
DLList<Double> s1 = new DLList<>(5.3);

double x = 9.3 + 15.2;
s1.insertFront(x);

We’ll spend a lot more time with generics later, but here are the rules of thumb you’ll need:

  • In the .java file implementing your data structure, specify your “generic type” only once at the very top of the file.

  • In .java files that use your data structure, specify desired type once:

    • Write out desired type during declaration.
    • Use the empty diamond operator <> during instantiation.
  • When declaring or instantiating your data structure, use the reference type.

    • int: Integer
    • double: Double
    • char: Character
    • boolean: Boolean
    • long: Long
    • etc.

Arrays

Getting Memory Boxes

To store information, we need memory boxes, which we can get in Java by declaring variables or instantiating objects. Examples:

int x;
/* Gives us a memory box of 32 bits that stores ints. */
Walrus w1;
/* Gives us a memory box of 64 bits that stores Walrus references. */
Walrus w2 = new Walrus(30, 5.6);
/* Gives us a memory box of 64 bits that stores Walrus references, 
 * and also gives us 96 bits for storing the int size (32 bits) and 
 * double tuskSize (64 bits) of our Walrus. */

Arrays are a special kind of object which consists of a numbered sequence of memory boxes.

  • To get ith item of array A, use A[i].

  • Unlike class instances which have have named memory boxes.

Arrays

Arrays consist of:

  • A fixed integer length (cannot change!)

  • A sequence of N memory boxes where N=length, such that:

    • All of the boxes hold the same type of value (and have same # of bits).
    • The boxes are numbered 0 through length-1.

Like instances of classes:

  • You get one reference when its created.

  • If you reassign all variables containing that reference, you can never get the array back.

Unlike classes, arrays do not have methods.

Like classes, arrays are (almost always) instantiated with new.

Three valid notations:

x = new int[3];
/* Creates array containing 3 int boxes (32 x 3 = 96 bits total). 
 * Each container gets a default value. */
y = new int[]{1, 2, 3, 4, 5};

int[] z = {9, 10, 11, 12, 13};
/* Can omit the new if you are also declaring a variable. */

All three notations create an array, which we saw before comprises:

  • A length field.
  • A sequence of N boxes, where N = length.

As an aside: In Oracle’s implementation of Java, all Java objects also have some overhead. Total size of an array=192 + KN bits, where K is the number of bits per item.

Array Basics:

Just figure out the syntax by yourself through the following example.

int[] z = null;
int[] x, y;
 
x = new int[]{1, 2, 3, 4, 5};
y = x;
x = new int[]{-1, 2, 5, 4, 99};
y = new int[3];
z = new int[0];
int xL = x.length;
 
String[] s = new String[6];
s[4] = "ketchup";
s[x[3] - x[1]] = "muffins";
 
int[] b = {9, 10, 11};
System.arraycopy(b, 0, x, 3, 2);

在这里插入图片描述

Arraycopy
System.arraycopy(b, 0, x, 3, 2); //(In Java)
#(In python):
x[3:5] = b[0:2] #List Slice Assignment

Two ways to copy arrays:

  • Item by item using a loop.

  • Using System.arraycopy , takes 5 parameters:

    • Source array
    • Start position in source
    • Target array
    • Start position in target
    • Number to copy

arraycopy is (likely to be) faster, particularly for large arrays. More compact code.

  • Code is (arguably) harder to read.
2D Arrays
Arrays of Array Addresses

Array Boxes Can Contain References to Arrays!

int[][] pascalsTriangle;
/* Array of int array references. */
pascalsTriangle = new int[4][];
/* Create four boxes, each can store an int array reference */
int[] rowZero = pascalsTriangle[0];
 
pascalsTriangle[0] = new int[]{1};
pascalsTriangle[1] = new int[]{1, 1};
pascalsTriangle[2] = new int[]{1, 2, 1};
/* Create a new array with three boxes, storing integers 1, 2, 1,
 * respectively. 
 * Store a reference to this array in pascalsTriangle box #2. */
pascalsTriangle[3] = new int[]{1, 3, 3, 1};
int[] rowTwo = pascalsTriangle[2];
rowTwo[1] = -5;
 
int[][] matrix;
matrix = new int[4][]; //Creates 1 total array.
matrix = new int[4][4]; //Creates 5 total arrays.
 
int[][] pascalAgain = new int[][]{{1}, {1, 1},{1, 2, 1}, {1, 3, 3, 1}};
  • Syntax for arrays of arrays can be a bit confounding. You’ll learn through practice (much later).
matrix = new int[4][4]; //Creates 5 total arrays.

在这里插入图片描述

Arrays vs. Classes

Arrays and Classes can both be used to organize a bunch of memory boxes.

  • Array boxes are accessed using [] notation.

  • Class members are accessed using dot notation.

  • Array boxes must all be of the same type.

  • Class members may be of different types.

  • Both have a fixed number of boxes/members.

Array indices can be computed at runtime.

int[] x = new int[]{100, 101, 102, 103};
int indexOfInterest = askUser();
int k = x[indexOfInterest];
System.out.println(k);
$ javac ArrayDemo.java
$ java ArrayDemo
What index do you want? 2
102

Class member variable names CANNOT be computed and used at runtime.

String fieldOfInterest = "mass";
Planet earth = new Planet(6e24, "earth");
double mass = earth[fieldOfInterest];	
System.out.println(mass);
$ javac ClassDemo.java
ClassDemo.java:5: error: array required, 
   but Planet found.
   
   double mass = earth[fieldOfInterest];
                            ^
  • Dot notation doesn’t work either.
String fieldOfInterest = "mass";
Planet earth = new Planet(6e24, "earth");
double mass = earth.fieldOfInterest;	
System.out.println(mass);
$ javac ClassDemo.java
ClassDemo.java:5: error: cannot find Symbol 
   double mass = earth.fieldOfInterest;		                   
                              ^
   symbol:   variable fieldOfInterest
   location: variable earth of type Planet
Another view

The only (easy) way to access a member of a class is with hard-coded dot notation.

int k = x[indexOfInterest];  	/* no problem */
 
double m = p.fieldOfInterest;  /* won't work */
double z = p[fieldOfInterest]; /* won't work */
/* No (sane) way to use field of interest */

double w = p.mass;             /* works fine */

The Java compiler does not treat text on either side of a dot as an expression, and thus it is not evaluated.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值