Commit 003941d5 authored by michael lundquist's avatar michael lundquist
Browse files

Adding some notes from ch 3, Almost done with it.

parent 64326c43
......@@ -47,4 +47,230 @@
- You can make a semi-random number that's much faster than a truly random number by initializing a pseudorandom number with a truly random seed using `java.util.Random.setSeed()` or using the `java.util.Random` constructor and passing the seed parameter.
- `java.util.Random` methods:
- `nextBoolean()`
\ No newline at end of file
- `nextBoolean()` returns the next pseudorandom __boolean__ value
- `nextDouble` returns the next pseudo random __double__, between 0.0 and 1.0
- `nextInt()` returns the next pseudorandom __int__
- `nextInt(n)` returns the next pseudorandom __int__ between 0 and n
- `setSeed(s)` sets the speed of this pseudorandom number generator to the __long__ s
- see the `Examples.randomExample()` in the ch3_code folder
### 3.1.4 Simple Cryptography with Character Arrays
- __cryptography__ involves encrypting plaintext to ciphertext and decrypting it back to plain text.
- The __Caesar cipher__ was an early form of cryptography.
- Because Strings are immutable, editing them takes forever. To get around this, programmers make an array of characters so they can edit each letter in the array individually.
- To do this, java has:
- the method `S.toCharArray()` that converts a String object (in this case S) to a character array
- A String constructor that takes a character array
- If you subtract two characters, you get an integer result of subtracting their ascii values. This can be useful.
### 3.1.5 Two-Dimensional Arrays and Positional Games
- Two-dimensional arrays are often used to represent 2D positional games like chess, checkers, tic-tac-toe...
- Java uses arrays of arrays to define two-dimensional arrays.
- See exercise P-8.67 for tic-tac-toe.
## 3.2 Singly Linked Lists
- Insertion into arrays and deletion from arrays is arduous. __Linked lists__ are an array alternative that avoids these problems.
- Linked lists are a collection of *nodes* that for a linear sequence where one node references the next and/or previous node.
- *singly linked* lists only reference the next or previous node, not both
- Linked lists must keep a reference to the first node aka the *head*, else the linked list be un-referenced and garbage collected.
- When you insert a new element at the head, the new element becomes the head and points to the old head.
- To delete the head, simply reassign the head variable to the next element.
- The last node of a linked list is the *tail*. Unless it is stored, the tail must be found by *traversing* the linked list starting at the head.
- Note, the tail can be identified because it has null as its next reference.
- traversing a linked list is aka *link hopping* or *pointer hopping*
- When inserting a new element at the tail of a linked list, the old tail points to the new element, and the new element points to null
- to delete the tail, if your linked list is singly linked you must traverse the whole array so you can get the element before the tail. In a doubly linked list, this is easier.
- Linked lists often store their size, so you don't have to traverse them to figure it out.
- Unlike arrays, linked lists can be any size.
- In their implementation they added a parameterized type for the singly-linked list to store, and added a nested node class to encapsulate it to prevent improper use.
## 3.3 Circularly Linked Lists
- A circularly linked list's tail points to the head as its next element. So there's no real beginning or end of the linked list.
- applications of circularly linked lists:
- __round-robin CPU__ scheduling where tasks are chosen from a queue, allowed to run for a certain amount of time (aka *alotted a time slice*), and added back to the queue if they exceed that amount of time. Circularly linked lists reduce the overhead for round-robin scheduling because tasks don't need to be added to or removed from anywhere, the CPU just moves to the next task in the linked list.
- card games where players take turns in a circle.
- bus routes
- Their implementation:
- They have a `rotate()` method that moves the tail to its next element.
- Storing the head is pointless, because it's the same thing as the tail's next element
- They have a *first* method that gets the first element of the linked list.
- First and rotate is traded off when traversing the list.
- Elements are inserted after the tail and become the new head.
## 3.4 Doubly Linked List
- In Doubly linked lists, each node has a pointer to the next node and to the previous node.
- maintaining the previous node means you don't have to traverse the list to find the previous node. This means you can delete any node without having to traverse the list to find its previous and next elements.
- You could even delete the tail without traversing!
#### Header and Trailer Sentinels
- Using dummy __sentinel__ (aka __guard__) nodes for the head and tail that are never deleted.
- remember, before we used null as the tail's next element
- in other words, sentinels can demarcate a doubly linked list.
- These dummy nodes are called __header__ and __tailer__
- The header's prev and the trailer's next node are still null, but you never have to assign null to something, you just stop when you see it.
#### Advantages of Using Sentinels
- Sentinels simplify logic by:
- keeping the header and trailer nodes constant.
- Making insertion and deletion the same at any point in the list.
- You never have to insert into an empty list.
- Inserting at the head is similar to inserting at the tail
#### Inserting and Deleting with a Doubly Linked List
You start with this:
```graphviz
digraph{
node[shape="record"];
rankdir=LR;
header[label="header|{<f0>|<f1>|<f2>&#xb7}"];
trailer[label="trailer|{<f0>&#xb7|<f1>|<f2>}"];
header:f2->trailer:f0;
trailer:f0->header:f2;
}
```
And insert some data:
```graphviz
digraph{
node[shape="record"];
rankdir=LR;
header[label="header|{<f0>|<f1>|<f2>&#xb7}"];
trailer[label="trailer|{<f0>&#xb7|<f1>|<f2>}"];
elem[label="node|{<f0>&#xb7|<f1>some data|<f2>&#xb7}" fillcolor = lightblue];
//not sure if fillcolor is valid.
header:f2->elem:f0;
elem:f2->trailer:f0;
trailer:f0->elem:f2;
elem:f0->header:f2;
}
```
- It's important to note, that even if no node points to a node, in a linked list, it will be deleted by the garbage collector even if it points to other things (has a next/prev). In this example, the node with the data "garbage" will be deleted by the garbage collector because no elements point to it eventhough it points to other elements:
```graphviz
digraph{
node[shape="record"];
splines=true;
rankdir=LR;
header[label="header|{<f0>|<f1>|<f2>&#xb7}"];
trailer[label="trailer|{<f0>&#xb7|<f1>|<f2>}"];
elem[label="node|{<f0>&#xb7|<f1>some data|<f2>&#xb7}" fillcolor = lightblue];
garbage[label="node|{<f0>&#xb7|<f1>garbage|<f2>&#xb7}" fillcolor = lightblue];
//not sure if fillcolor is valid.
header:f2->elem:f0;
elem:f2->trailer:f0;
trailer:f0->elem:f2;
elem:f0->header:f2;
garbage:f0:w->elem:f2:e;
garbage:f2:e->trailer:f0:w;
}
```
### 3.4.1 Implementing a Doubly Linked List Class
- Their class has these methods:
- size
- isEmpty
- first
- last
- addFirst(e)
- addLast(e)
- removeFirst
- removeLast
- addBetween(e,e) for general insertion, this is private
- ch 7 recovers this in more detail
## 3.5 Equivalence Testing
- In java, `==` will test if two variables point to the same object.
- Often this definition of `==` is too narrow. For example, two different String objects with the same value would return `false` when compared with `==`.
- Fortunately, java's Object superclass provides the `.equals(Object o)` method that you can override to determine when two objects of your class type equal each other.
- When writing an `.equals(Object o)` method, keep in mind the following general mathematical principles for how equality works:
- __Treatment of null__: `x.equals(null)` should always return false
- __Reflexivity__: x = x
- in java: `x.equals(x)` is true
- __Symmetry__: if x=y, y=x
- in java: if `x.equals(y)`, `y.equals(x)`
- __Transitivity__: if a=b, and b=c, a=c
- in java, if `a.equals(b)`, and `b.equals(c)`, then `a.equals(c)`
- Inheritance and generics can make obeying these principles difficult
### 3.5.1 Equivalence Testing with Arrays
- Because arrays are a reference type, not technically a class, their `.equals(Object o)` method behaves the same as `==`
- To compare if the value in the array are equal, use `Arrays.equals(Object[] a, Object[] b)`.
- This will check if `a` and `b` are the same length, then sequentially compare each element in `a` and `b` using their `.equals(Object o)` method
- Note this will fail with 2 or more dimensions because it will use `a[k].equals(b[k])`, which will be the same as `a[k] == b[k]` because `a[k]` is an array
- To compare arrays with 2 or more dimensions, use `Arrays.deepEquals(Object[] a, Object[] b)`.
### 3.5.2 Equivalence Testing with Linked Lists
- Testing equivalence with linked lists is similar to testing equivalience if arrays. Length is compared, then elements are compared sequentially.
- They also say *erasure* is the reason you can't get a parameterized type's class, and therefore can't construct new objects of that type.
## 3.6 Cloning Data Structures
- When making a copy of an object, you need to decide what instance variables of the new object will also be copies, and what instance variables will refer to the same objects as the original object.
- Remember, when two variables refer to the same objects, changes made to that object can be seen at both variables.
- obviously static variables aren't copied
- The `Object` superclass provides the `clone` method, that produces a *shallow copy* of an object where all the new object's instance variables are the same as the old object's, but the new object is a different object.
- `clone()` is __protected__ in `Object` because it's usually not what you want. To use clone, you must formally override it and declaring it public.
- If you try to use it without overriding you'll get a `CloneNotSupportedException`
```java
public class Rando{
/*
simplest clone method, that's probably not what you want as it does a shallow copy
*/
@Override
public Object clone(){
return clone();
}
}
```
- In reality, the clone method usually constructs a new object using the constructor.
### 3.6.1 Cloning Arrays
- As discussed above, assignment just copies a reference to a variable, clone does a shallow copy.
- Here's some code to deep clone a 1d array:
```java
public Object[] deepClone(Object o){
Person[] guests = new Person[contacts.length];
for(int k=0; k < contacts.length; k++)
guests[k] = (Person) contacts[k].clone();
}
```
-
\ No newline at end of file
import java.util.Arrays;
import java.util.Random;
public class Examples{
public static void main(String[] args){
randomExample();
}
/**
* fills an array with random elements
*/
public static void randomExample(){
int[] data = new int[10];
Random rand = new Random();
rand.setSeed(System.currentTimeMillis());
for (int i =0; i < data.length; i++){
data[i] = rand.nextInt(100);// next number between 0 and 100
}
int[] orig = Arrays.copyOf(data, data.length);
System.out.println("Arrays equal before sort: " + Arrays.equals(data, orig));
Arrays.sort(data);
System.out.println("Arrays equal after sort: " + Arrays.equals(data, orig));
System.out.println("orig = " + Arrays.toString(orig));
System.out.println("data = " + Arrays.toString(data));
}
}
\ No newline at end of file
import java.util.Arrays;
public class Examples{
public class Exercises{
public static void main(String[] args){
ScoreBoard.test();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment