//***********************************************//
//*******Linked Lists - November 30th, 2016*****//
//*********************************************//

-We get Taylor today!

-About the homework: there's a general panic going around: TA lab is flooded, getting a ton of emails, etc. Yes, it's a lot, there's a lot of stuff to look through, it's DENSE, you have to understand code you haven't written, etc. BUT: The POINT of the homework is to handle the GUI and show a basic understanding of JavaFX. If I can hit "Start" and the map pops up, and there's some sort of menu showing, AND I can sort-of interact with the map, then that's already a pretty good grade!
    -I haven't even written the rubric since I wasn't sure how hard this would be! Trust me, if most people are struggling, you won't get an "F" for getting a basic interactable map to show up (now, would it be a "B"?)
    -The due date will NOT be extended, though; you had 2 weeks to do this. MORE IMPORTANTLY, we want to finish grading by the end of the semester
-MAKE SURE TO COMPILE HOMEWORK 6 CORRECTLY; there will most likely be NO REGRADE CHANCES due to how close to the end we are
-------------------------------------------------------

-So, we start with data structures now!
-In real life, data structures are really important. MORE IMPORTANTLY (kinda):
    -Linked lists appear ALL THE TIME in job interviews. You're expected to know these things forwards and back, along with the rest of the major data structures; problems involving these will be a MAJOR way companies

-So, arrays are a list of spaces for objects all in one contiguous set of memory; the problem though, is that we can have gaps in these spaces, so the array indices themselves have NO IDEA where the next piece of data is
-A LINKED LIST is a collection of data where each piece of data has a reference (usually a pointer) to the next piece of data in the list

    [data] -> [data] -> [data]

-So, in order to iterate through this, we just follow the data pieces to wherever each points next!
-These data pieces are each called NODES; the first node if called the HEAD
    -Head is usually stored in a reference variable; if the head is null, then there are NO elements in the list
    -The last element in the list is called the TAIL;
        -If there's only one item in the list, it is both the head AND the tail

-Now, there is a tradeoff: if we want to just get, say, the 3rd piece of data, we can't just jump there like in an array; we'd have to iterate through the list until we find the piece of data

-There are many variations to the linked list; instead of having a TAIL variable, we can just check if the pointer to the next node is "null", in which case, we're at the end of the linked list!
    -Head, though...you always need somewhere to start, so basically every implementation has a Head variable
-The one we've discussed is a "Singly Linked List", as there's only a single reference in each node to its neighbors
-There's also a "Doubly Linked List", each node has a reference to both the next AND previous node, allowing us to go both forward and backwards
    -HEAD usually doesn't have a link to the TAIL, though (except in one, specific case...which you'll learn about in 1332 :)   )

    [HEAD] <-> [node] <-> [node] <-> [node] <-> [TAIL]

-So, as far as actually coding this thing:
    -The data could be an object, a primitive, etc.; it could be ANYTHING
        -In practice, it'll always technically be an object, if only due to wrapper classes
    -So, it can be ANYTHING? Sounds like a job for...Generics!

    public class Node<E> {...}

    -So, we'll have TWO pieces of instance data (for a singly-linked list)- A reference to the next node ("private Node<E> next") and something to actually hold the data ("private E data")
    -Along with that, we'll need getters and setters for the data, and a constructor to actually instantiate a node:

    public Node(E data) {
        this.data = data;
        next = null;
    }

    public Node(E data, Node next) {
        this.data = data;
        this.next = next;
    }

    //getters / setters self-explanatory

    -Okay, so we've coded the Node class! Now, though, we have to make the actually class for the LinkedList itself (public class LinkedList<E>)
    -The class itself should just NEED one piece of instance data: a reference to the head

    "public class LinkedList<E> {
        Node head = null;

        public LinkedList(E head) { //just have to pass in a data; the user doesn't even have to know what a linked list is
            this.head = new Node(head);
        }

        public LinkedList() {
            this.head = null;
        }"

        -So, we've got the basic data structure; now we want to be able to add things to the LinkedList!
            -To do this, we need to get to the end of the list, then add our piece of data as the next

        "public void add(E data) {
            Node curNode = head;
            while(curNode.next() != null) { //starts at head, then goes to the end of the list
                curNode = curNode.next();
            }
            curNode.setNext(new Node(data));
        }"

    -Great! We can make a new LinkedList, we can add stuff to it...but what if we want to remove something from the list?

    "public void remove(E data) {
        Node curNode = head;
        while(!curNode.getData().equals(data) && curNode.next != null) { //keep going until we reach the node we're looking for, or the end of the list
            curNode = curNode.next();
        }
        ...
    }"

    -Now we have a problem, though: once we remove the node, the node before it, that used to be pointing at the node we removed, won't be pointing at anything; that'll break the list! So, we have to make the previous node point to the next node instead:

    ...[node] -> [node] -X *poof* [node] -> ...
    ...[node] -> [node] --------> [node] -> ...

    -So, we need a 2nd pointer to keep track of the node we just looked at
        -Don't have to worry about setting curNode to null, as in Java, any object with no references to it (no way of reaching it) will be automatically removed
    -EDGE CASES: What if data isn't in the list?
                    -Program won't know what to do! Could do something like, "if (curNode.getData())"
                -What if we remove the head? Then the list doesn't know where the head is!
                    -We'll just have an "if (curNode.equals(head))" and set the next node to be the new head
    -ALWAYS consider the edge cases; in real life, you will ALWAYS have to deal with them, and in job interviews, catching the edge cases is what makes a good programmer stand out