CIS265 Lecture Notes: Custom Made Linked Lists

PERSON class public class Person implements Comparable {

private String name; private int age; // ------public Person(String name, int age) { super(); this.name = name; this.age = age; } // ------

public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // ------public String toString() { return " Name:" + name + " Age:" + age; } // ------@Override public int compareTo(Person otherPerson) { if ( this.age == otherPerson.getAge() ) return 0; else if ( this.age > otherPerson.getAge()) return 1; else return -1; } } NODE class public class Node< E extends Comparable > implements Comparable > {

private E element; private Node next; private Node previous;

// ------public Node(E dataObject) { //Person p = new Person(theName, theAge); element = dataObject; next = null; previous = null; } // ------

public E getElement() { return element; }

public void setElement(E element) { this.element = element; }

public Node getNext() { return next; }

public void setNext(Node next) { this.next = next; }

public Node getPrevious() { return previous; }

public void setPrevious(Node previous) { this.previous = previous; }

// ------

public String showNode() { return element.toString(); }

@Override public int compareTo(Node other) { E otherElement = other.getElement(); E thisElement = this.getElement(); return thisElement.compareTo(otherElement); } } LINKED LIST class public class LinkedList > {

private Node head; private Node last; private int count; // ------public LinkedList() { head = null; last = null; count = 0; } // ------public Node getHead() { return head; }

public void setHead(Node head) { this.head = head; }

public Node getLast() { return last; }

public void setLast(Node last) { this.last = last; }

public int getCount() { return count; }

public void setCount(int count) { this.count = count; }

// ------// insert new node at the end of the list public void add(Node newNode) {

if (count == 0) { head = newNode; last = newNode; count = 1; return; }

count++; last.setNext(newNode); newNode.setPrevious(last); last = n; } // ------// add new node in the list’s natural order public void addInOrderVersion1(Node newNode) { if (count == 0) { head = newNode; last = newNode; count = 1; return; }

count++; Node ptr = head; E element = null; boolean keepGoing = true; while (keepGoing && ptr != null) { element = ptr.getElement(); if (element.compareTo(newNode.getElement()) < 0) { ptr = ptr.getNext(); } else { keepGoing = false; } }// while

if (ptr == null) { last.setNext(newNode); newNode.setPrevious(last); last = newNode; } else { newNode.setNext(ptr); newNode.setPrevious(ptr.getPrevious()); if (ptr == head) { head = newNode;

} else { ptr.getPrevious().setNext(newNode); ptr.setPrevious(newNode); } }

} // ------public void addInOrderVersion2(Node newNode) { count++; // new node is the first to be inserted in the list if (count == 0) { head = newNode; last = newNode; return; }

// new node goes at the beginning of the list if ( head.compareTo(newNode) > 0 ){ //new node is smaller than first element newNode.setNext(head); head.setPrevious(newNode); head = newNode; return; } // new node goes at the end of the list if ( last.compareTo(newNode) < 0 ){ //new node is larger than last element newNode.setPrevious(last); last.setNext(newNode); last = newNode; return; }

Node ptr = head; Node prior = null;

while ( ptr != null) { if ( newNode.compareTo(ptr) < 0) break; prior = ptr; ptr = ptr.getNext();

}// while

// place news node in between existing elements newNode.setNext(ptr); newNode.setPrevious(prior); prior.setNext(newNode); ptr.setPrevious(newNode);

}

// ------public void showList() { System.out.printf("\n<>\n", head, last, count); E element; Node ptr = head; while (ptr != null) { element = ptr.getElement(); System.out.println(ptr.toString() + "\t" + element.toString()); ptr = ptr.next; } }

} DRIVER package csu.matos; public class Driver1 {

/** * Creating a custom-made linked list holding Person data * */ public static void main(String[] args) {

Node p1 = new Node(new Person("AAA", 111)); Node p2 = new Node(new Person("BBB", 222)); Node p3 = new Node(new Person("CCC", 333));

Node head = null; Node tail = null; Node ptr = null;

head = p1; tail = p3;

p1.setNext(p2); p2.setNext(p3); p2.setPrevious(p1); p3.setPrevious(p2);

ptr = head; while (ptr != null) { System.out.println(ptr + "\t" + ptr.showNode()); ptr = ptr.getNext(); }

System.out.println("Here is the list");

// ------

LinkedList list = new LinkedList();

list.add (p1); list.add(p2); list.add(p3);

list.showList();

System.out.println("Here is the list-after addInOrder");

list.addInOrderVersion2(new Node (new Person("XXX", 150)) );

list.showList();

}// main } CONSOLE

csu.matos.Node@2a9931f5 Name:AAA Age:111 csu.matos.Node@2f9ee1ac Name:BBB Age:222 csu.matos.Node@67f1fba0 Name:CCC Age:333

Here is the list

<> csu.matos.Node@2a9931f5 Name:AAA Age:111 csu.matos.Node@2f9ee1ac Name:BBB Age:222 csu.matos.Node@67f1fba0 Name:CCC Age:333

Here is the list-after addInOrder

<> csu.matos.Node@2a9931f5 Name:AAA Age:111 csu.matos.Node@1ee7b241 Name:XXX Age:150 csu.matos.Node@2f9ee1ac Name:BBB Age:222 csu.matos.Node@67f1fba0 Name:CCC Age:333 VERSION 2

Minor changes are made here to enhance the management of Generic Data Objects accepted by the custom made doubly- linked list

.

DRIVER package csu.matos; public class Driver {

/** * Author: V. Matos * Date: 4-11-2013 * Goal: Create a generic UDT (User-defined Data Type) * to support linked-list operations. * Minor changes to enhance the previous version * (look for Generic-Data-Type and treatment of toString) */ public static void main(String[] args) {

// create a custom-made doubly-linked list MyList mylist = new MyList();

mylist.addLast(new Person("Daenerys", "123456789")); mylist.addLast(new Person("Arya", "111222333")); mylist.addLast(new Person("Sansa", "222333444")); mylist.addLast(new Person("Tyrion", "333444555")); mylist.addLast(new Person("John", "444555666"));

System.out.println( mylist.showControlData() ); mylist.showForward(); mylist.showBackward();

System.out.println("\nSearching...."); String key = "222333444"; Node foundNode = mylist.find(key); if ( foundNode == null) { System.out.println("KEY NOT FOUND" + key); } else { Person foundPerson = foundNode.getData(); System.out.println( "FOUND " + foundPerson); }

// try to delete node found above if ( mylist.removeNode(foundNode) ) { System.out.println("After attempt to delete..."); mylist.showForward(); }

// insert Person at a given position (fake ArrayLit's insert) if ( mylist.insert( 2, new Person("Brain", "999888777")) ) { mylist.showForward(); }

}//main } MyList Class package csu.matos; public class MyList > { // class variables private Node first; private Node last; private int count;

// contructor public MyList() { this.first = null; this.last = null; this.count = 0; } // mutators public Node getFirst() { return first; } public void setFirst( Node n1) { this.first = n1; } public Node getLast() { return last; } public void setLast(Node last) { this.last = last; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } // user-defined methods public String showControlData(){ return String.format( "\nCONTROL\tFIRST:%s \n\tLAST: %s \n\tCOUNT:%d", this.getFirst(), this.getLast(), this.getCount()); }

// ------// Add new node at the end of the list: public int addLast(E data){ // place given data in a new node n Node newNode = new Node(data);

if ( count == 0){ first = newNode; last = newNode; } else { // place new element at the end of the existing list last.setNext(newNode); newNode.setPrevious(last); last = newNode; } return ++count; }

// Add new node at the end of the list: public int addFirst(E data) { // place given data in a new node n Node newNode = new Node(data);

if (count == 0) { first = newNode; last = newNode; } else { // place new element at the beginning of the existing list first.setPrevious(newNode); newNode.setNext(first); first = newNode; } return ++count; } public Node find( String key){ E data = null; Node n = first; while ( n != null){ data = n.getData(); if ( data.compareTo(key) == 0) return n; else n = n.getNext(); }

return null; }//find public void showForward(){ int index = 0; System.out.println("\nTraversing list (forward ...)" + count); Node n = this.getFirst(); while ( n != null ){ System.out.println( index++ + n.showData() ); n = n.getNext(); } }//showForward public void showBackward(){ int index = count - 1; System.out.println("\nTraversing list (backward ...)" + count); Node n = this.getLast(); while ( n != null ){ System.out.println( index-- + n.showData() ); n = n.getPrevious(); } }//showForward

// remove node at give memory location public boolean removeNode(Node nodeToBeDeleted){ //NAIVE: we assume node is part of the list if (count == 0 || nodeToBeDeleted == null ) return false;

if ( count == 1 && ((nodeToBeDeleted == first) || (nodeToBeDeleted == last ))){ first = last = null; count= 0; return true; } // Check cases: nodeToBeDeleted is first, last, or in between Node left = nodeToBeDeleted.getPrevious(); Node right = nodeToBeDeleted.getNext(); count--;

if ( nodeToBeDeleted == first){ right.setPrevious(null); first = right; return true; }

if ( nodeToBeDeleted == last){ left.setNext(null); last = left; return true; }

// NAIVE: assuming nodeToBeDeleted is in current chain // (a better way is to keep extra ptr. to control node) left.setNext(right); right.setPrevious(left); return true; }//removeNode

public boolean insert(int pos, E newData) { Node newNode = new Node(newData); if ( pos > count || pos < 0) return false;

// add newData at the end of the list; if ( pos == count -1){ addLast(newData); return true; }

if ( pos == 0 ){ addFirst(newData); return true; }

Node currentNode = first; for(int i=0 ; i< pos; i++){ currentNode = currentNode.getNext(); } // connect newNode with existing neighbors(left, current) Node left = currentNode.getPrevious(); newNode.setPrevious(left); newNode.setNext(currentNode); currentNode.setPrevious(newNode); left.setNext(newNode); count++; return true; }//insert

} Node Class package csu.matos; public class Node > { // class variables E data; Node next; Node previous;

// constructor public Node(E data) { this.data = data; this.next = null; this.previous = null; } // mutators

public Node() { this.data = null; this.next = null; this.previous = null; } public E getData() { return data; } public void setData(E data) { this.data = data; } public Node getNext() { return next; } public void setNext(Node next) { this.next = next; }

public Node getPrevious() { return previous; }

public void setPrevious(Node previous) { this.previous = previous; }

// user-defined methods public String showData() { String format = "\n[NODE \tCURR:\t %s ]\n" + "[NODE \tNEXT:\t %s\n\tPREVIOUS:%s \n\tDATA:\t %s ]"; return String.format(format, this, this.getNext(), this.getPrevious(), this.getData() ); } } Person Class

package csu.matos; public class Person implements Comparable { // class variables private String name; private String ssn; private Object thisPerson;

// constructor(s) public Person(String name, String ssn) { super(); this.name = name; this.ssn = ssn; thisPerson = this; }

public Person() { super(); this.name = "n.a"; this.ssn = "-1"; thisPerson = this; }

// mutator(s) public String getName() { return name; }

public void setName(String name) { this.name = name; }

public String getSsn() { return ssn; }

public void setSsn(String ssn) { this.ssn = ssn; } // ======// user-defined methods

public String showData(){ return String.format( "\n\t[PERSON LOC: %s]\n\t[PERSON NAME:%s SSN:%s]", this, this.getName(), this.getSsn() ); }

@Override public String toString(){ // done this way to stop recursion-observe that plain: this // calls this.toString(). String thisLoc = getClass().getName() + '@' + Integer.toHexString( hashCode() ); //return thisLoc; return String.format( "\n\t[PERSON LOC: %s]\n\t[PERSON NAME:%s SSN:%s]", thisLoc, this.getName(), this.getSsn() );

}

// compare Person data with a give SSN key-value @Override public int compareTo(String key) { String mySsn = this.getSsn(); if (mySsn.compareTo(key) == 0) return 0; else if (mySsn.compareTo(key) > 0) return 1; else return -1; } }

CONSOLE

CONTROL FIRST:csu.matos.Node@62fcf06c LAST: csu.matos.Node@4c0c7539 COUNT:5

Traversing list (forward ...)5 0 [NODE CURR: csu.matos.Node@62fcf06c ] [NODE NEXT: csu.matos.Node@45e41830 PREVIOUS:null DATA: [PERSON LOC: csu.matos.Person@1f01b29] [PERSON NAME:Daenerys SSN:123456789] ] 1 [NODE CURR: csu.matos.Node@45e41830 ] [NODE NEXT: csu.matos.Node@3a8721bd PREVIOUS:csu.matos.Node@62fcf06c DATA: [PERSON LOC: csu.matos.Person@7db81d4f] [PERSON NAME:Arya SSN:111222333] ] 2 [NODE CURR: csu.matos.Node@3a8721bd ] [NODE NEXT: csu.matos.Node@428c6e04 PREVIOUS:csu.matos.Node@45e41830 DATA: [PERSON LOC: csu.matos.Person@118aeabe] [PERSON NAME:Sansa SSN:222333444] ] 3 [NODE CURR: csu.matos.Node@428c6e04 ] [NODE NEXT: csu.matos.Node@4c0c7539 PREVIOUS:csu.matos.Node@3a8721bd DATA: [PERSON LOC: csu.matos.Person@373968f1] [PERSON NAME:Tyrion SSN:333444555] ] 4 [NODE CURR: csu.matos.Node@4c0c7539 ] [NODE NEXT: null PREVIOUS:csu.matos.Node@428c6e04 DATA: [PERSON LOC: csu.matos.Person@1a18c28a] [PERSON NAME:John SSN:444555666] ]

Traversing list (backward ...)5 4 [NODE CURR: csu.matos.Node@4c0c7539 ] [NODE NEXT: null PREVIOUS:csu.matos.Node@428c6e04 DATA: [PERSON LOC: csu.matos.Person@1a18c28a] [PERSON NAME:John SSN:444555666] ] 3 [NODE CURR: csu.matos.Node@428c6e04 ] [NODE NEXT: csu.matos.Node@4c0c7539 PREVIOUS:csu.matos.Node@3a8721bd DATA: [PERSON LOC: csu.matos.Person@373968f1] [PERSON NAME:Tyrion SSN:333444555] ] 2 [NODE CURR: csu.matos.Node@3a8721bd ] [NODE NEXT: csu.matos.Node@428c6e04 PREVIOUS:csu.matos.Node@45e41830 DATA: [PERSON LOC: csu.matos.Person@118aeabe] [PERSON NAME:Sansa SSN:222333444] ] 1 [NODE CURR: csu.matos.Node@45e41830 ] [NODE NEXT: csu.matos.Node@3a8721bd PREVIOUS:csu.matos.Node@62fcf06c DATA: [PERSON LOC: csu.matos.Person@7db81d4f] [PERSON NAME:Arya SSN:111222333] ] 0 [NODE CURR: csu.matos.Node@62fcf06c ] [NODE NEXT: csu.matos.Node@45e41830 PREVIOUS:null DATA: [PERSON LOC: csu.matos.Person@1f01b29] [PERSON NAME:Daenerys SSN:123456789] ]

Searching.... FOUND [PERSON LOC: csu.matos.Person@118aeabe] [PERSON NAME:Sansa SSN:222333444] After attempt to delete...

Traversing list (forward ...)4 0 [NODE CURR: csu.matos.Node@62fcf06c ] [NODE NEXT: csu.matos.Node@45e41830 PREVIOUS:null DATA: [PERSON LOC: csu.matos.Person@1f01b29] [PERSON NAME:Daenerys SSN:123456789] ] 1 [NODE CURR: csu.matos.Node@45e41830 ] [NODE NEXT: csu.matos.Node@428c6e04 PREVIOUS:csu.matos.Node@62fcf06c DATA: [PERSON LOC: csu.matos.Person@7db81d4f] [PERSON NAME:Arya SSN:111222333] ] 2 [NODE CURR: csu.matos.Node@428c6e04 ] [NODE NEXT: csu.matos.Node@4c0c7539 PREVIOUS:csu.matos.Node@45e41830 DATA: [PERSON LOC: csu.matos.Person@373968f1] [PERSON NAME:Tyrion SSN:333444555] ] 3 [NODE CURR: csu.matos.Node@4c0c7539 ] [NODE NEXT: null PREVIOUS:csu.matos.Node@428c6e04 DATA: [PERSON LOC: csu.matos.Person@1a18c28a] [PERSON NAME:John SSN:444555666] ]

Traversing list (forward ...)5 0 [NODE CURR: csu.matos.Node@62fcf06c ] [NODE NEXT: csu.matos.Node@45e41830 PREVIOUS:null DATA: [PERSON LOC: csu.matos.Person@1f01b29] [PERSON NAME:Daenerys SSN:123456789] ] 1 [NODE CURR: csu.matos.Node@45e41830 ] [NODE NEXT: csu.matos.Node@4f8bff68 PREVIOUS:csu.matos.Node@62fcf06c DATA: [PERSON LOC: csu.matos.Person@7db81d4f] [PERSON NAME:Arya SSN:111222333] ] 2 [NODE CURR: csu.matos.Node@4f8bff68 ] [NODE NEXT: csu.matos.Node@428c6e04 PREVIOUS:csu.matos.Node@45e41830 DATA: [PERSON LOC: csu.matos.Person@702d2da4] [PERSON NAME:Brain SSN:999888777] ] 3 [NODE CURR: csu.matos.Node@428c6e04 ] [NODE NEXT: csu.matos.Node@4c0c7539 PREVIOUS:csu.matos.Node@4f8bff68 DATA: [PERSON LOC: csu.matos.Person@373968f1] [PERSON NAME:Tyrion SSN:333444555] ] 4 [NODE CURR: csu.matos.Node@4c0c7539 ] [NODE NEXT: null PREVIOUS:csu.matos.Node@428c6e04 DATA: [PERSON LOC: csu.matos.Person@1a18c28a] [PERSON NAME:John SSN:444555666] ]