Data Structures using Java Part 6: Linked Lists Part 1

Lists
—–
Store a list of integers as an array.

Disadvantages:
1. Suppose you want to insert an item at beginning or middle of the list. This takes time propotional to the length of the array.
2. Arrays have a fixed length.

public class List{

	int[] a; // a reference
	int lastItem; // index to the last item of the list

	public List(){
	a = new int[10];
	lastItem = -1;
	}

	public void insertItem( int newItem, int location){ // inserts a new item at a location in the list
		int i;
		for(i = lastItem; i>= location; i--){  // this moves all the items in the list towards the right till the location is emptied
				a[i+1] = a[i];
		}
	a[location] = newItem; // puts the newItem value into the empty location slot
	lastItem++; // increment number of items
	}
}

Linked Lists ; A recursive data type
—————————————
1. A list that is made up of data structures called nodes.
2. Each node stores two things:
– an item
– a reference to the next node in the list

Singly linked list
public class ListNode{
	int item;
	ListNode next; // a reference called next pointing to next node in the list

}

// creating 3 different nodes
ListNode l1 = new ListNode();
ListNode l2 = new ListNode();
ListNode l3 = new ListNode();

// initialising values for items
l1.item = 10; // giving a value for item for l1
l2.item = 100;
l3.item = 1000;

//linking the nodes
l1.next = l2; // this links the lists
l2.next = l3;
l3.next = null; // l3 does not point to anything

Node operations
—————–

// the constructor for the ListNode
public ListNode(int item, ListNode next){

	this.item = item;
	this.next = next;
}

// for the last node
public ListNode(int item){
	this(item, null);
}

ListNode node1 = ListNode(7, new ListNode(0, new ListNode(6)));

Advantages over arrays
————————-
1. Inserting an item in the middle of the linked list takes constant amount of time if you have a reference to previous node.
2. Moreover, the list can keep growing until the memory runs out.

Inserting a new item after “this”

public void insertAfter(int item){

next = new ListNode(item, next); // the later "next" is the older value on whatever object we can like l2
}

l2.insertAfter(2);

The last statement creates a new node with the item value 2 and the next parameter is the next value of l2( old ) which points to l3. Now the new “next” value is assigned to the newly created node.

Disadvantages
—————
1. Finding the nth item of the linked list takes time propotional to the length of the list n, number of items in the list. With arrays you can do this in constant time.

// to find the nth item in a list
public ListNode nth( int location){

	if(position == 1){  // the current item
		return this;
	}else if ((position < 1) || ( next == null)){  // error checking
		return null;
	}else{
		// we will use recursion
		return next.nth(position -1); // -1 as we the list size keeps on decreasing
	}
}

ListNode l2 = l.nth(4);

Lists of objects
—————–
1. Reference any object by declaring a reference of type Object.

public class SListNode{ // a singly linked list

	public Object item;
	public SLinkNode next;
}

A List Class
————-
There are 2 problems with SListNodes:
1. Insert new item at the begining of the list.

x = new SListNode("Soap", x); // problem when two references to same node

2. How do you represent an empty list?

x = null; // runtime error if you try to call any method on x

Solutions
———-
1. Seperate SList class that maintains the head of the list.

public class SList{
	private SListNode head; // points to the beginning of the linked list
	private int size;  // keeps track of the number of SListNodes

	public SList(){ // initialisation
	head = null; // the idea of an empty list.
	size = 0;
	}

	public void insertFront(Object item){ // we now insert it here and not in SListNode
		head = new SListNode(item, head);
		size++;
 	}
}
Data Structures using Java Part 6: Linked Lists Part 1

Data Structures using Java Part 5: More on arrays, initialisers, function parameters, do loop, break ,continue and final

Automatic Array Construction
——————————–

int[][] table = new int[x][y];

1. Creates an array of x referecnces to array.
2. Creates x arrays of y int.

 

Initialisers
————

Human[] b = {amy, danny, Human(" Jacky")};
int[][] c = {{2,4,5},{45},{2,4,5,6},{1,3,},{x},{y+3, 4}};

int[] a,b,c; // specifies the type and all are reference arrays
int a[], b, c[][]; // a is 1D , b is just an int and c is 2D; proper C style
int[] a , b[]; // a is 1D and b is 2D

Array of objects
——————
When you create an array of objects, Java does not automatically create the objects for you. And you need to create a loop for the same.

Fraction[] f = new Fraction[5];
for (int i = 0; i<5; i++) {
	f[i] = new Fraction[i][6];
}

Main functions parameters
—————————-

class Echo{

	public static void main(String[] args ){
		for(int i =0; i< args.length; i++){
			System.out.println(args[i]);
		}
	}

}

1. String[] args consists of the arguments you type in at the unix prompt.
2. args.length gives the number of arguments.
For example if we type this in the unix prompt:

$ java Echo my name is Daniel

my
name
is
Daniel

Note that java Echo is not a part of the argument list.

do loops
——-
1. Executes the loop body at least once.

 do{
 s = keybd.readLine(); // read a line from the keyboard
 process(s); // do something
 }while(s.length > 0); //  if size of s is 0 , then exit the loop
 

There might be an ambiguity as in what to do if the user enter anything in the beginning. This will cause the process method to break down and ultimately an error occurs. This can be corrected by the following code:

The break and continue statement
————————————-
break statement always exits the innermost “switch” or loop enclosing the break.

 // method one
 s = keybd.readLine();
 	while(s.length > 0){       // process only if the length is greater than 0
 		process(s);
		 s = keybd.readLine();
 	}

Disadvantage:
1. Repeated code s = keybd.readLine()

 

 // method two: with the break statement
 while (true){

 	s = keybd.readLine();
 	if(s.length == 0)
 		break;

 	process(s);
 }
 

Disadvantage:
1. Obfuscated
2. Loop is not aligned with natural alignment

 

Continue
———
1. It only applies to loops
2. Doesnt exit the loop.
3. Another iteration my commence if condition of do/while/for loop is satisfied.

 loop:
 while(i < 9){
 	stuff:{
 		switch(s){
 		case 1: break;
 		case 2: break stuff; // breaks the loop and continues at statement 1
 		case 3: continue; // jumps out of switch but still inside while loop and so next iteration occurs
 		case 4: continue loop; // same as above

 		}
 		//statement 1
 	}
	//statement 2
 }
 

Constants
———–
“final” keyword – value that can never be changed.

BAD:

if (month == 2){ // if 2 represents something like a month february and it is difficult to change

GOOD:

 public static final int FEB =2; // change code only in one place
 if (month == FEB){
 }

For any array x, x.length is considered to be a final field and thus cannot be changed!

Data Structures using Java Part 5: More on arrays, initialisers, function parameters, do loop, break ,continue and final

Data Structures using Java Part 4: Loops, bounds, arrays, multidimensional arrays

Loops
——
1. while

// fucntion to check for a prime number
public static boolean isPrime( int n){

	int divisor = 2;
	while(divisor < n){
		if (n % divisor == 0){ // this is the while loop
			return false; // since n is divisible by a number
		}
		divisor++;
	}
	return true; // checked all values from 2 to n-1
}

If n <= 2, the loop wont execute.

2. for

for(initialise; test; next){
// intitalise gets executed first
while (test){
	//statements;
	//next;
}
}
// check for the prime number using a for loop
public static boolean isPrime( int n){

for(int divisor =2 ; divisor < n ; divisor ++){
		if (n % divisor == 0){ // this is the while loop
			return false; // since n is divisible by a number
		}
	return true; // checked all values from 2 to n-1
}

Loop bounds
————-

// Print all the prime numbers in the range from 2 to n
public static void printPrimes( int n) {
int i;
for(i =2; i < n ; i++){ // error as the condition should be i <= n
	if (isPrime(i)){
		System.out.println(" " + i);
	}
}
}

Arrays
——–

An object consists of numbered list of variables. Each is a primitive type or a reference to a object.

char[] c; // reference to an array of characters which can be of any length
c = new char[4]; // creates the array and the size is mentioned
c[0] = 'b'; // we use the single quotes for characters
c[3] = 't';
c[8] = 'y'; // Runtime exception
int a = c.length; // gives the length of the array
c.length = 20; // gives a compile time error

Multidimensional arrays
————————
2D array : Is an array of references to 1D arrays. For example the Pascal’s triangle: In mathematics, Pascal’s triangle is a geometric arrangement of the binomial coefficients in a triangle. It is named after mathematician Blaise Pascal.

Pascals Triangle
// creates and returns a pascal triangle using 2D arrays
public static int[][] pascalTriangle (int n){

 int[][] pt = new int[n][]; // allocates n references for the array.

 for( int i = 0; i< n ; i++){
 	pt[i] = new int[i+1];
 	pt[i][0] = 1;
 	for (int j = 1; j< i; j++){
 		pt[i][j] = pt[i-1][j-1] + pt[i-1][j];
 	}
 	pt[i][j] = 1;
 }
 return pt;

 }
 
Data Structures using Java Part 4: Loops, bounds, arrays, multidimensional arrays

Data Structures using Java Part 3: Primitives, java.lang, conditionals, return

Primitive Types:
—————-
1. byte : an 8 bit integer (-128 to 127)
2. short: a 16 bit integer (-32768 to 32767)
3. int: a 32 bit integer (- 2 billion to well +2 billon)
4. long: a 64 bit integers (well..) eg. 124L or 134l
5. double: a 64 bit floating point number eg.67.0
6. float: a 32 bit floating point number eg. 12.4f or 5.5F
7. boolean: its true or false
8. char: a single character

A double or float should always have a decimal point, else it will be treated as an int.

                       Object Types            Primitive Types
                       ---------------           ----------------
1. Contains         Reference              Value
2. Definition        Class                    Built into java
3. Creation         "new"                    "4", true
4. Initialisation    constructor            Default value generally 0 or false
5. Usage            methods                Operators (+, - , *)

java.lang library
—————–
1. Math class

a = Math.abs(y); // finds the absolute value of y and there are more methods like sqrt, sin

2. Integer class

int x = Interger.parseInt("2010"); // converts the string into a number

3. Double class

double d = Double.parseDouble("3.412"); // converts string to double

Integers can be assigned to variables of longer type. Otherwise you need to cast the type explicitly to get the desired valure and to avoid compile time errors.

int i = 100;
long l = 45l;
l = i;// this is okay
i = l;// compile time error
i = (int)l; //this is called a cast. throws the 32 bits off for the int!

Conditionals
————
1. if..else

boolean pass = score &gt;= 75;
if (pass){
System.out.println("you passed");
}else{
// that is your score is less than 75
System.out.println("loser!");
}

2. switch

The switching case cannot be a floating point and definitely not an object. All other types can be used.

switch(month){

case 2 : days = 28;
break;
case 4:
case 6:
case 9:
case 11: days = 30;
break;
default: days = 31;
break;
}

The return keyword
———————-
1. Causes a method to end immediately when executed.
2. Control returns to the calling method.

public void something (int x){

if ( x == 10){
return; // if x is 10 do not continue with the function
}
// the rest of the code runs if not equal to 10
}

3. Useful for returning a value from a function, which is a method to return a non void type value. The add() function just returns the sum of a and b to the calling function.

public int add(int a , int b){
return (a + b);
}
Data Structures using Java Part 3: Primitives, java.lang, conditionals, return

Data Structures using Java Part 2: Classes, constructors, this, static and lifetime

Defining Classes
—————–
Fields:
1. Variables stored inside objects
2. Used to store data
3. Also known as instance variables

amy.introcude(); // methode call
amy.age;// age is the instance variable

class Human{

	public int age;
	public String name;

	public void introduce(){
	System.out.println("Hi! I am  "+ name + " and I am  "+ age + "years old!");
	}

	public void copy(Human original){
	age = original.age;
	name = original.name;
	}
}

Each Human object can have different values of age and name.

Human amy = new Human();
amy.age = 12;
amy.name = "Amy";
amy.introduce(); // prints out Hi! I am Amy and I am 12 years old!

Human linda = new Human();
amy.copy(linda); // copies content of linda object into amy object

Constructors
————–

class Human{

	public int age;
	public String name;

	public void introduce(){
	System.out.println("Hi! I am  "+ name + " and I am  "+ age + "years old!");
	}

	public void copy(Human original){
	age = original.age;
	name = original.name;
	}

	public Human(String newname){
	age = 12;
	name = newname;
	}

}

The constructor is used to initialised the name of the object to whatever name we pass to it and the age as shown is set to 12 by default. So this code can be converted to:

Human amy = new Human();
amy.age = 12;
amy.name = "Amy";

// this is to be written in place of the last 3 lines of code.. not together
Human amy = new Human("Amy");

Java always provides a default constructor for you. When you creat a new constructor, the default constructor wont be created. If you need onem create one explicity!. The default constructor if written explicitly would look like this:

public Human(){

}

You can also override the default constructor like:

public Human(){
	age = 0;
	name = "Null";
}

The this keyword
——————-

“amy.introduce()” implicitly passes an extra parameter, an object (amy) as a parameter called “this”.

public Human(){
	this.age = 0;
	this.name = "Null";
}

// this method is in the Human class
public void change(int age){

	String name = "Chan";
	this.age;
	this.name = name;
}

The parameters and the local variable always take precedence in methods. Just “age” implies the parameter and “name” the local variable. So we use “this.age”. You cannot change the value of “this”. Complier error if you try to change.

amy.change(10); //Parameters and local variables are obtained. Whatever is in “amy” will be copied onto “this”.

The static keyword
———————

Static field:
1. a single variable shared by a whole class of objects.
2. also called class variables.
3. System.out is a static field.

 class Human{

	public int age;
	public String name;
	public static int number;

	public Human(){
		number++;
	}
}

int kids = Human.number/4;

Static method:
1. Doesnt implicitly take an object as a parameter.
2. In a static method there is no “this”.

 class Human{

	public int age;
	public String name;
	public static int number;

	public Human(){
		number++; // increment by 1 each time an object is created.
	}

	public static void printHumans(){
	System.out.println(number); // number as it is inside the class
	}
}

Life time of variables
———————–
1. A local variable is gone when the method ends.
2. An instance variable, not static, lasts as long as the object lasts.
3. A class variable, static, lasts as long as program is running.

Data Structures using Java Part 2: Classes, constructors, this, static and lifetime

Data Structures using Java Part 1: String objects and I/O in Java

Objects and methods
———————–

String s1; //declare a String variable
s1 = new String(); // assign it a value
String s2 = new String(); // both the steps combined

s1 = "Hello"; // assign the value into the object s1
s2 = s1; // s1 and s2 points to the same object, same value
s2 = new String(s1); // creates a new String object and copies the value of s1 into s2

The 3 String constructors
—————————-
1. new String() constructs a empty string, ie no characters

String s1; //declare a String variable
s1 = new String(); // assign it a value
String s2 = new String(); // both the steps combined

2. Stick something in quotes.

s1 = "Hello"; // assign the value into the object s1

3. Takes a parameter.

s2 = new String(s1); // creates a new String object and copies the value of s1 into s2; the constructor parameter is s1

NOTE: Constructors always have the name of the class

 

String Methods
—————–
1. Conversion into uppercase

s2 = s1.toUpperCase();

2. To concatenate two Strings

String name = s2.concat(" says hello!");
String say = "*".concat(name).concat("*");

Unlike in C, in Java String objects are immutable, ie their contants never change.

 

Java I/O Classes
——————
Objects in System classes for interacting with user

1. System.out
a PrintStream object that outputs to the screen.

2. System.in
a InputStrem object thats reads stuff from the keyboard.

3.readLine method
is defined on a BufferedReader objectm is used to read a whole line.

How do we construct a BufferReader?
With a InputStreamReader.
How do we construct a InputStreamReader?
We need an InputStream.
How do we construct a InputStream?
System.in is one.

The InputStream objects, their job is to read raw data from the keyboard. An unformatted bit stream. The InputStreamReader object takes the raw data and compose them into characters. Java usually uses unicode 2 byte long characters. The ufferedReader object takes the raw characters and converts them into text. This is done in 3 steps for modularity reasons.

import java.io.*;

class SimpleIO{

public static void main( String args[] ) throws Exception{

BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in)
);

System.out.println(keyboard.readLine());
}

}

To use the Java library, other than java.lang, you need to import that library. You need to import the java.io for the ISR and the BR. The java program always begins with the “main”  method.

Data Structures using Java Part 1: String objects and I/O in Java