table of contents introduction.............................................7 the idea of...

177
How To Program © Walter Milner 2013                            Page 1 

Upload: others

Post on 11-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

How To Program © Walter Milner 2013                            Page 1 

Page 2: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

How To Programby Dr. Walter Milner

All contents copyright © 2013 Walter William Milner. All rights reserved.

Comments to [email protected] are welcome.

About the authorDr. Milner's first degree was in the Natural Sciences at Cambridge University. Since then he has worked in education teaching science maths and computing, and has post­graduate qualifications in teaching at secondary level and higher education. His PhD was awarded by the University of Birmingham for a thesis concerned with cognitive aspects of novice programmers learning Java. 

How To Program © Walter Milner 2013                            Page 2 

Page 3: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Table of ContentsIntroduction.............................................7

The idea of Programming..........................9

Programming languages are formal languages..............9

A programming language IS a set of grammar rules......9

Java is a general purpose language..............................9

There are only 50 reserved words in Java.....................9

Program text and machine state.................................10

Java is a high level language......................................10

Starting Java..........................................12

Setting up Java..........................................................12

Hello World................................................................12

Variable declarations..................................................13

Types.........................................................................14

Literals.......................................................................14

Type casts..................................................................15

Comments.................................................................15

When it goes wrong....................................................16

Some suggestions for debugging.................................18

Algorithms.............................................20

Recipe steps...............................................................20

Exchange values........................................................20

Where the term comes from........................................22

Algorithms and code structure................23

Algorithm examples................................25

Larger of two values...................................................25

The conditional statement..........................................25

Repetition – while.......................................................27

The for loop................................................................28

break and continue....................................................29

Random numbers.......................................................30

Adding up..................................................................30

Counting....................................................................31

Extreme values..........................................................31

Square root................................................................32

Euclid's Algorithm......................................................33

Arrays....................................................35

Arrays and loops........................................................36

Sequences..................................................................37

Iteration and recursion...........................38

Iteration.....................................................................38

Linear searches..........................................................38

Recursion...................................................................39

Binary search.............................................................43

Equivalence of recursion and iteration........................44

Data structures......................................45

Linked lists................................................................45

How To Program © Walter Milner 2013                            Page 3 

Page 4: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Defining a linked list in Java......................................45

Pretty­printing a linked list.........................................48

Adding to a list...........................................................49

Searching a list..........................................................50

Deleting a node..........................................................51

Ordered Lists.............................................................52

Self­organising lists....................................................54

Object oriented programming..................55

Packages....................................................................55

Static and non­static..................................................56

Time and space complexity.....................58

Introduction...............................................................58

List insertion..............................................................58

Big O notation............................................................59

Insertion in an ordered list.........................................60

Array data structures.............................62

Standard implementation...........................................62

Re­sizable arrays........................................................63

Access control, wrapper classes and import................63

Strings...................................................67

Unicode......................................................................67

The String class.........................................................67

The Java API..............................................................68

Objects and references...............................................68

String processing.......................................................68

Comparing objects and references..............................69

Sort algorithms......................................71

The sort concept.........................................................71

Bubble sort................................................................72

Bubble sort is stable and in place...............................73

Time complexity of a bubble sort................................74

Quicksort...................................................................74

 Stacks...................................................77

Linked list implementation.........................................77

OOP inheritance.........................................................77

Uses of stacks ­ reversing things.................................78

Uses of stacks ­ return address..................................78

Uses of stacks ­ expression evaluation........................80

Uses of stacks ­ programming languages....................81

Time Complexity........................................................81

Exceptions.................................................................81

More on inheritance...................................................82

What is the point of inheritance?................................84

The Object class.........................................................84

Abstract Data Types...............................86

Queues..................................................87

Operations.................................................................87

Implementation ­ Linked List......................................87

How To Program © Walter Milner 2013                            Page 4 

Page 5: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Inner classes..............................................................89

Implementation – Array..............................................90

Priority queues...........................................................92

Namespaces...............................................................93

Generics.................................................95

A generic linked list....................................................95

The Java Collections framework.................................97

Radix sort..................................................................98

Sets......................................................102

Variadic arguments..................................................102

 Iterators..............................................105

Using an index.........................................................105

Making an iterator....................................................105

Interfaces.................................................................106

The Iterator interface................................................107

The Iterable interface................................................109

Trees....................................................110

Terminology.............................................................110

Ordered Trees..........................................................111

Enums.....................................................................112

A generic Tree..........................................................113

The Comparable interface.........................................113

Tree traversals.........................................................114

Tree sort..................................................................116

Breadth­first traversal..............................................117

Depth­first traversal.................................................118

Pretty printing a tree................................................119

Balanced trees.........................................................120

Maps....................................................121

Hash tables..............................................................121

Collisions.................................................................123

Deletions..................................................................125

The Collections Framework HashMap.......................126

hashCode() and .equals()..........................................129

Memoization.............................................................131

Graphs.................................................133

Representations.......................................................134

Kruskal's Algorithm..................................................137

Coding Kruskal........................................................137

Graphics Algorithms.............................140

Background.............................................................140

A Swing window.......................................................140

Drawing an image....................................................142

Bitwise operators......................................................143

Bit shifts..................................................................144

A better binary.........................................................144

Bit masks.................................................................145

Pixel bit manipulation..............................................146

Using transparency..................................................148

How To Program © Walter Milner 2013                            Page 5 

Page 6: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Plotting a pixels........................................................149

Line drawing algorithms...........................................150

An integer­arithmetic only line..................................153

Anti­aliasing.............................................................154

An anti­aliasing algorithm........................................155

Floodfill....................................................................156

File Structures and algorithms.............159

Reading and writing text files....................................159

Opening and closing files..........................................161

Buffers.....................................................................161

 Serial and random access........................................163

A Map in a file..........................................................164

File devices..............................................................166

How Java works...................................168

How Computers work...............................................168

Machine code...........................................................169

Using an assembler and linker.................................169

Hello world on Linux................................................170

Using ASCII..............................................................172

Doing arithmetic......................................................173

High level language programming.............................174

Java bytecode...........................................................175

How bytecode works.................................................176

Abstraction..............................................................177

How To Program © Walter Milner 2013                            Page 6 

Page 7: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Introduction

The purpose of this text is to teach how to program. 

Most programming books are about C or Java or Visual Basic ­ they are about programming languages. As a result, students will often say ­ I know the language, but I don't know how to write programs. This is about how to write programs. 

Learning how to program is mostly done by writing programs, so we need to use some programming language. We use Java, because it is very 'expressive', easy to read and write, is open­source, and runs on Windows, Linux, Mac OS X, and many other platforms. But it is not about Java. It is about how to write programs. It is intended for novice programmers, not professionals.

Students often think 'I will learn language X, then have a career as a professional programmer writing X all my life'. Then they ask ­ 'what is the best language to learn to get a job?'.

This is a mistake. Competent programmers know, and use, several languages. For web applications in 2013, that often involves PHP, SQL, JavaScript and html and css (which are mark­up languages not programming languages). So you 

need to know several languages to get a job. The question 'what is the best language' is meaningless. And the idea that a language must be 'current' is also wrong. COBOL was designed in 1959 ­ but Google 'COBOL jobs' to see that people are still recruiting.  

But this is not so difficult. All programming languages are fundamentally the same (if they are Turing complete ­ Google it). But they often take different approaches, and learning them deepens your understanding. 

There are two key concepts to understand ­ algorithm and data structure.

1. An algorithm is a type of recipe for solving a problem. Some are very simple, some are not. Programming means finding (or inventing) a suitable algorithm, and writing it in a programming language.

2. A data structure is a way of arranging a set of data items.Examples are lists, stacks, queues and trees. Each data structure has a set of algorithms which are appropriate for it.

This is not an encyclopeadia of data structures and algorithms. The idea is to provide an understanding of theseideas, and how they are used to write programs.  

How To Program © Walter Milner 2013                            Page 7 

Page 8: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Most of the code examples here  work in Java version 6, with a handful needing Java 7. The compiler will tell you if there is a version issue.

Again – this is not a book about Java, so not all aspects are covered – in particular there is nothing about concurrency. But it will teach you how to program. After that – you just write the code.

Some other good books and links

The Java Programming Language by Arnold, Gosling and Holmes. The book about Java by the people who designed it.

The Really Big Index of tutorials from Oracle

The Java Language Specification. This is a formal specification of what Java is.

Data Structures and Algorithms by Aho, Hopcroft and Ullman. Classic text on the subject. Examples in Pascal. Around $5 second­hand

The Art of Computer Programming  by D. Knuth. This man basically invented Computer Science. In 4 volumes. Lots of maths.

How To Program © Walter Milner 2013                            Page 8 

Page 9: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The idea of Programming

As you work through this, you should try the exercises and write lots of code. It probably won't work, at first. Read the section 'When it goes wrong'.

Programming languages are formal languages

This is in distinction to natural languages like English or 

Arabic or Cantonese. Formal languages have a set of syntax rules ­ rules of grammar which can be used to checkif a program is valid or not. Natural languages also have grammar rules. But if you say to a Frenchman 'Bonjour, comment allez­nous?' he will not reply 'Syntax error'. He will think that you are not very good at French, and will reply slowly and simply as if talking to an idiot. But in programming, any syntax error will stop your program from running.

A programming language IS a set of grammar rules

Java is not a piece of software, but a grammar. Using the grammar, anyone can create the software needed to write and run Java. There is a 'standard implementation' but youdo not have to use it.

The grammar of Java is published in the Java Language Specification. This is a link to it.

Some languages are proprietary ­ they are owned by commercial companies. Others are developed and agreed bya community process ­ Java is like this. C and C++ are agreed by ISO committees. Visual Basic and C# are proprietary Microsoft languages.

Java is a general purpose language

It is designed to be able to do everything which a programming language can do (technically, it is 'Turing complete'). So long as someone writes the code for it.

There are only 50 reserved words in Java

A reserved word  has a special meaning in a Java program.'for',  'if' and 'while' are some reserved words. The programmer can use other words, as names for variables (and methods and classes and other stuff), and these are called identifiers. But you cannot name a variable with a reserved word.

So how can you write programs that will do anything, when you only have 50 words, when English has around 600,000 words in use? That's what this text is about. Read it and you will know.

How To Program © Walter Milner 2013                            Page 9 

Page 10: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Program text and machine state

Here is part of a program ­ the text of a Java program:

int x,y,z;x=2;y=3;x=4;z=x+y;System.out.println(z);

It prints out 7. Think about why.

The program text has 6 lines, each of which is an instruction to the computer. The instructions are carried out in sequence, from the top down. The first line says that x y and z are ints – whole numbers. The next 4 instructions change the values of variables ­ in other words, they changethe state of the machine. It is likely that this will mean that subsequent instructions will have a different effect.

That means we must follow down the program text, and track how that will alter variable values ­ like this:

State

Instruction x y z

x=2 2

y=3 2 3

x=4 4 3

z=x+y 4 3 7

Java is a high level language

A low level language is about the computer and how it works. Low level language programs are written in machine code or assembler. They make references to the hardware details of the computer ­ so they are specific to a particular processor chip and OS. There are some tutorial examples later.  

High level languages focus on the the problem to be solved, and express the solution in the program as clearly as the language and the programmer can. They do not refer to detials of the particular computer being used. This has two advantages. First we do not need to learn all the details of a particular processor chip and the OS. Second, our program 

How To Program © Walter Milner 2013                            Page 10 

Page 11: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

will run on any machine which has the appropriate software. In our case, that is a Java runtime. So for example the Java programs in this text will run identically on a Windows machine or Linux or iOS.

High level languages, to varying degrees, can use the idea ofabstraction. See later. 

How To Program © Walter Milner 2013                            Page 11 

Page 12: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Starting Java

Setting up Java

To run Java programs, you need to install some software called the Java Runtime Environment, or JRE.

To write Java, you need the JRE, and the Java Software Development Kit, or JDK.

Once you have these, you can write Java programs just using a simple text editor, such as Notepad in Windows. 

But instead you can use an IDE such as NetBeans or Eclipse. Most people argue that it is best to start with a texteditor, then move on to an IDE after a little experience.

All this is free software.

The download and install instructions vary between different operating systems and their different versions. Google and follow the one for your platform. 

Hello World

There is a tradition that the first program to write in a new language is one that simply outputs 'Hello world!'. Here we go:

public class Test {

public static void main(String args[]) {

System.out.println("Hello world!");

}}

1. Type (or better, copy and paste) this into a text editor, like Notepad on Windows or gedit on Ubuntu. Save it with the filename Test.java ( not test.java or anything else).

2. At the command line, in the folder where you saved it, compile it by typing

javac Test.java

3. Launch the application from the command line by:

java Test

For example, on a Linux platform:

How To Program © Walter Milner 2013                            Page 12 

Page 13: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Exercise

1. Change the letters in “Hello world” and compile and run the program again

2. As well as normal characters, we can output some 'control characters'. One of these is n, for new line. But we need to 'escape' this, as \n, to show we do not mean normal n. So change it to

“Hello\nworld\n” and see what happens. 

Variable declarations

A variable is some data which can change, and which has aname. At any time, the value of the data is held in memory, and the name lets the system work out where it is held – its address in memory. We can assign a value to a variable, which stores a value in memory at the correct place.

For example

x = 3;

This is an assignment statement, which stores a 3 at 

location x. The ; at the end makes it a statement.

But in Java, before we can use a variable, it must be declared. This means we tell the compiler what type the data is. For example:

int x;

This tells the compiler that x is an int – an integer, a whole number.

Here is a little program which goes on to output the value:

How To Program © Walter Milner 2013                            Page 13 

Page 14: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

public static void main(String args[]) {int x;x = 3;System.out.println(x);

}}

Try this out.

Types

A 'type' is a kind of data.

In Java there are two sorts of types, primitives and reference types. We will look at references later.

An int is an integer – a whole number. We will use ints a lot, since they are nice and simple. An int can be positive ornegative, up to about 2 thousand million

There is also a long, which is even bigger than an int.

For  numbers with decimals, we use a double. Like

double d;d=3.1415926;

An alternative to double is float. Doubles use 8 bytes of memory, but floats only use 4 bytes, with smaller range andaccuracy.

For single characters, we use char. Like

 

char c;c = 'A';

Note that is 'A' and not “A”. Double quotes enclose strings, which are different.

There is also a true or false type, called a boolean – such as

boolean finished;finished=false;

Literals

A literal is a value in source code. For example in 

x = 2 + 3;

there are two literals, 2 and 3.

How To Program © Walter Milner 2013                            Page 14 

Page 15: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Literals have type, as well as variables. The type of 2 is an int. If you want a long, you say 2L.

Similarly 2.0 is type double, in 8 bytes. If you want a 4 byte float, say 2.0f.

'X' is a char literal. 

Type casts

Sometimes we need to change data from one type to another. This is called a cast or typecast.

If you change from a smaller to a bigger type (float to doubleor int to long), this is no problem. For example

int x = 2;long v = x;

The x is held in 4 bytes. This is stored in the 8 bytes of the long, with the other 4 bytes filled with 0s. No problem. This is called an implicit typecast.

But casting to a smaller type is an issue. For example:

If we put the 8 bytes of a long into the 4 bytes of an int – weare likely to lose some bits. If we still want to do it, we need an explicit type cast, which in this case is:

long v = 2L;int x = (int) v;

In fact 2 only requires two bits ( 2 = binary 10 ) so we are not really losing any significant bits.

Comments

In program text we can put comments, which are pieces of text which the compiler ignores. Comments are used to put in date, author, version number, and notes of explanation for things which are not obvious.

A line comment starts with a // and extends to the end of the line:

// Author: Walter Milner

A block comment starts /* and ends */ and can cover several lines

How To Program © Walter Milner 2013                            Page 15 

Page 16: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

/* Author: Walter Milner Date: 13 September 2013 Purpose: Illustrate block comments */

When it goes wrong

Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? 

• Brian Kernighan, "The Elements of Programming Style", 2nd edition, chapter 2 

This is probably the most important part of this text.

When you start to write Java, most of it will be wrong. Lateron, only some of it will be wrong.

Two points when getting started:

1. Your filename MUST be named the same as your class name, with a .java extension, exactly, including capitalisation.

So

public class SomeName{..}

must be saved as SomeName.java – exactly, and nothing else.

2. Your code structure must be (to start with)

public class Test {

public static void main(String args[]) {.. your code goes here..}}

You don't have to name the class  Test – but you may as well.

Once you've checked those two – here is rule 3:

3. Read and understand the error message

The error message tells you two things – what the error was, and where it is (what line number in your code). Error messages are hard to understand at first, and there is a temptation to ignore them as meaningless. But they are full of meaning, and you must try to understand them – they correspond to your knowledge of Java.

This applies both to compile time syntax errors and runtimeexceptions – explained next.

4. Syntax errors are easy

How To Program © Walter Milner 2013                            Page 16 

Page 17: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

when you have some experience. For example

This is in Eclipse, but NetBeans does something similar. There is a red wavy line under 'x' – so the problem is to do with 'x'. It's at line 8 – so this is where the problem is. The error message is 'x cannot be resolved to a variable'. The compiler tracks the variables it has seen – and it cannot match 'x' with one of them. One possibiity is that you forgot to declare x as a local variable:

int x;x=4;

 Another example:

  

Here the red wavy line is under '4', but the '4' is not the problem. The error message gives a pretty big clue – 'insert ;to complete the statement' So you forget the trailing ';'.

 Third example:

The '4.5' has the red wavy line, so the problem is about this.The error message is 'cannot convert from double to int'. So this is to do with data types, double and int. A little thoughtshould show the problem – you've declared x to be an int, 

How To Program © Walter Milner 2013                            Page 17 

Page 18: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

which is a whole number, then tried to assign a value whichis not a whole number. Depending on what 'x' represents, either declare it as a double, or asssign a whole number to it.

 5. Runtime exceptions

Sometimes code has no syntax errors, but when it runs, a 'runtime exception is thrown'. For example

int[] data=new int[5];data[5]=7;

 

When this runs, we get:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

at Test.main(Test.java:18)

We have not yet met arrays – no matter.

The exception name is ArrayIndexOutOfBoundsException. What does that mean? It must be about an array. What array? It occurs 'at Test.main(Test.java:18) That means at line 18. Line 18 is data[5]=7; so the array in question is 'data'. The problem is 'index out  of bounds', and it says 5, in red. So the problem is the 5 in data[5]. It is 'out of bounds'. Why?

The array data has been declared to have 5 elements, and these are numbered from 0, so allowed index values are 0 to4 inclusive. There is no element number 5, so we cannot store something in it. We probably need to change that to data[4].

If the exception name does not make sense to you – just Google it.

6 Incorrect output 

These are the only kinds of bugs which are difficult to fix, with some experience. The program runs, with no error messages or exceptions, but it does not do what it is supposed to. One example is in a graphics context, and you get a blank screen. Tricky.

Some suggestions for debugging

Write code in the smallest possible amounts between tests. In other words, do not write hundreds of lines of code, then check it works. If you do, the problem could be anywhere inthose hundreds of lines. Instead, write ten lines and check. If that does not work, you know the problem lies somewherein those ten lines.

How To Program © Walter Milner 2013                            Page 18 

Page 19: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Put System.out.println values at appropriate points. This tells you at least that code at that point is executing. Outputting values lets you check if variables have the values which you think they have. When you find one whichdoes not, you must work backwards. Where was it given that value? Why is it not what you thought?

Try commenting out code. You may have a block of code which is suspect. You might delete it. But if in fact it is OK, you have to write it again. So just temporarily put /* before and */ after. If it checks out OK, remove the comments – and look somewhere else.

Think a lot.

Work through the code on paper, tracing out variable values. Sometimes this is feasible. If you have thousands of loops, its not.

As a last resort, use a debugger. This is software which offers options like run to cursor, single step, jump over method calls, and outputting watch variables and expressions. This is a last resort since setting up a debugger often takes some time. 

Software testing is a specialist area. JUnit is a formal way of doing this. assert is a useful tool. But these notes are justintended to help if you have a problem doing the exercises in this text.

 

  

  

How To Program © Walter Milner 2013                            Page 19 

Page 20: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Algorithms

Recipe steps

An algorithm is a recipe for solving a problem. The recipe is a sequence of steps. Each step is an instruction to the computer to do something. A program is an algorithm expressed in a programming language.

What kind of steps or instructions can we have? Only six categories are allowed:

1. Input data. Algorithms always have some input data to work on.

2. Output data ­ the result of the algorithm. This might be a single number, or a whole set of related data.

3. Assign the value of an expression to a variable. The expression must be capable of being expressed in terms of basic arithmetic. So

x = 3+4

is OK. So is

y=sin(2) since a sine function can be calculated by basic arithmetic as accurately as we want.

4. Test if some condition is true. Like

if x>5...

The test can only be something we can work out using basicarithmetic ­ but we can use a very large amount of arithmetic if we need to.

5. Repeat other statements. This might be to to repeat one or more steps a given number of times, or until some condition is true. This is called iteration. So for example we can say 

repeat 10 times

6. Another algorithm. One algorithm can make use of another algorithm. This is a useful item of problem­solving ­we can split one difficult problem into several smaller problems, and solve each one with a simpler algorithm

So we can have just 6 kinds of steps ­ input, output, assignment, iteration, conditional and other algorithms.  

Exchange values

Suppose we have two variables, and we want to exchange their values:

x=1

y=2

How To Program © Walter Milner 2013                            Page 20 

Page 21: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

then after the exchange, y would be 1 and x 2. How to do this?

The obvious way isx=y

y=x

but this does not work. If we track the values:

x=1 x is 1

y=2 x is 1 y is 2x=y x is 2 y is 2y=x x is 2 y is 2

The problem is that the assignment x=y stored the value of y in x, so the initial value of x was lost.

We need an additional storage location to hold the initial value of x, which we can then write into y:

public class Test {

public static void main(String args[]) {int x,y; x=1; y=2;int temp; temp=x; x=y; y=temp; System.out.println(x+" : "+y); // 2 : 1

}}

We have found an algorithm to exchange the values of two variables. The actual algorithm is the 3 assignments:

temp=x

x=y

y=temp

Exercise

1. Try this out in a Java  program to check it works.

2. Suppose we have 3 variables, w, x and y, and we want to rotate their  values, w to x, x to y, and y to w. So for example:

How To Program © Walter Milner 2013                            Page 21 

Page 22: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Before After

w 4 9

x 7 4

y 9 7

Devise an algorithm and write a Java  program to do this. Test it works.

3. Can you rotate 4 values, w, x, y and z?

Where the term comes from

The word derives from the Latin version of Mu ammad ibn ḥMūsā al­Khwārizmī, an eighth century Persian mathematician who, amongst other things, set out the  beginnings of algebra in his text  “Al­Kitāb al­mukhta ar fī ṣ

isāb al­jabr wa­l­muqābala” ('The Compendious Book on ḥCalculation by Completion and Balancing').

How To Program © Walter Milner 2013                            Page 22 

Page 23: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Algorithms and code structure

We often want to use an algorithm several times in a program. We can do this by just typing out the code for the algorithm, repeatedly. But this is is not a good idea.  It wastes memory, since we have multiple copies of the same code. It risks bugs, if the code copies are not identical. And it hides the fact that we are doing the same thing, unless welook really closely and see that we have the same code several times.

A better solution is to put the code for the algorithm in a separate area, and just use it whenever we want to. We are talking about giving some structure to the program code – dividing it into several units, instead of just having one  block of code.

Other advantages of splitting code into small units include being able to test those units separately; the fact that it enables a programming team to work together, with each person working on a separate unit; and it means it might bepossible to re­use those units in other projects.

All programming languages allow this. The names of the units vary – sub­routines, modules, functions, procedures and sub­programs are some of them.

In Java, one way to do this is using something called a method.

For example, we might need to find the average of three numbers, many times. We just need to add them up and divide by three:

public class Test {

static double average(double x, double y, double z) {double result;result = (x + y + z) / 3.0;return result;}

public static void main(String args[]) {double a, b, c;a = 1.0;b = 3.0;c = 4.0;double av;av = average(a, b, c);System.out.println(av);}}

 Our code is now in two units. One starts 'public static void main..' and the other unit starts 'static double average..'. The purpose of 'main' is to be the point where the application starts. The purpose of 'average' is to find the average of three numbers.

The definition of the method starts as 'static double average..' and end with the 'return'.

The method is used (invoked) by av = average(a,b,c)

How To Program © Walter Milner 2013                            Page 23 

Page 24: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Exercise

Before we go through this in detail – try to modify this so it finds the average of four numbers.

The method definition header is

static double average(double x, double y, double z) {

We explain 'static' later.

The first 'double' is there because this is the return type of the method. The method calculates a value, and returns it, and we must say it this point what type is the returned value. It could have been int – but an average in general willnot be an integer, so we say double. Some methods just do something (for example, deleting a file), and do not return anything. For these, the return type is void.

After the name of the method, average, we have round brackets ( ) enclosing a list of formal parameters. The idea here is that sometimes we need to supply some data into the method, and this is done through these parameters – sometimes called arguments. We need to give the data type of each parameter, and a name for it.

The body of the method definition is in a block, enclosed { and }. Inside the block we declare a local variable, result, and use it to hold the calculated value. At the end of the method, we return this value.

The method is invoked in

av = average(a, b, c);

Here we have 3 actual parameters, a b and c. The values ofthe actual parameters are copied to the formal parameters, in order – so x gets the value of a, y gets b and z gets c. The returned value is assigned to the variable 'av'.

Exercise

Write a method called addUp which takes three integer parameters and returns their total. In main, test it.

How To Program © Walter Milner 2013                            Page 24 

Page 25: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Algorithm examples

Larger of two values

How can we find the larger of two values? We can use a conditional. If the first is larger than the second, the first is larger ­ otherwise the second is larger.

We can use an if to write a method which finds the larger oftwo values:

public class Test {

static int larger(int a, int b) {int bigger;if (a > b)bigger = a;

elsebigger = b;

return bigger;}

public static void main(String args[]) {int x, y;x = 3;y = 4;System.out.println(larger(x, y));}}

The conditional statement

A conditional, or 'if' statement, enables a program to execute different pieces of code, depending on data values. The idea is

if (something which is true or false)  {

  .. things to do if it is true

  }

else

  {

  .. thing to do if it is false

  }

The 'else' part is optional – so you then have

if (something which is true or false)  {

  .. things to do if it is true

  }

and if it is false, you simply go on to the next statement.

How To Program © Walter Milner 2013                            Page 25 

Page 26: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The curly brackets { and } form a block statement or compound statement.  This is a sequence of statements enclosed by { and }, and executed in the sequence. If you only want to do one thing, you can replace the block by one statement, like

if (a > b)result = a;else result = b;

This is wrong ­

if (a > b);result = a;

Do NOT put a semi­colon at that point.

The 'something which is true or false' is a boolean expression.  Here are some examples, using constants:

Expression Meaning Value Notes

4>3 Greater than True

4 < 3 Less than False

5 == 5 Equals True NOT =

3 >= 3 Greater thanor equal to

True

2 <= 3 Less than or  True

equal to

6 != (2+4) Not equal to False

!(4>3) Not greater than 

False

(2>1) && (5>4)

Logical AND True Like both 2>1 and 5>4

(1>3) || (2>1) 

Logical OR True Like either 1>3 or 2>1

&& and || are not the same as & and |. See later.

These can be as complicated as you like. For example:

if ( x>3 || (y==7) && !(z=4) )...

but the more complicated, the more likely it will be incorrect.

Use brackets to ensure things are done in the order you want.

The statements in a block can be any type, including an if, so you could say:

How To Program © Walter Milner 2013                            Page 26 

Page 27: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

if (..) { .. if (..) { .. } .. }

The indentation of the code in an if is important – you will go wrong if you do not do it. Most IDEs can correct indentation for you.

Exercise

1. Write a method which returns the largest of three values.

2. Test it with the following

input result

1, 2, 3 3

7,9,2 9

9, 2,1 9

­1,­2,­3 ­1

4,7,7 7

Repetition – while

One basic tool in an algorithm is to repeat some steps. If weneed to do something three times, we can just type out that statement three times. But if we need to do it 1000 times, that is impractical. Languages include control constructs which allow blocks of code to be repeated. These are known as loops.

One such construct in Java  is the while loop:

public class Test {

public static void main(String args[]) {int x = 0;while (x < 5) {System.out.println(x);

x++;}

}}

which outputs 0 1 2 3 4. x++; means to increment x by 1.

Exercise

1. Alter this so it outputs 1 2 3 4

2. Then change it so it outputs 1 2 3 4 5

3. Now change it so it outputs 2 4 6 8 10

How To Program © Walter Milner 2013                            Page 27 

Page 28: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

A while loop in Java  is like this:

.. some initialisation..while (.. something true or false.. ){.. some code to repeat..}

The 'something true or false.. is an expression which gives atrue or false value, as in an 'if' statement. That can use == or < or && and so on. If it is false the first time around, the loop body is never executed. If there is just one statement torepeat, that can replace the { block }.

There is a small variation on a while loop, which is a do.. while..:

public class Test {

public static void main(String args[]) {int x = 0;do {System.out.println(x);x++;

} while (x < 5);}}

This checks the condition at the end of the loop body, rather than at the start. This means the loop body will always execute at least once.

Exercise

Write while loops to output 

1. 0 to 100

2. 0 to 99

3. 20 down to 10

4. 20 down to 10 in steps of 2 ( 20 18 16.. 10 )

5. Can you output 1 to 5, 50 times?

The for loop

As well as a loop body, loops have 3 aspects:

1. Initialisation

2. When to continue, or stop

3. What to change every time around

A for loop has these three parts. 

For example:

How To Program © Walter Milner 2013                            Page 28 

Page 29: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

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

}}

After the for ( there are 3 parts, with ; between them:

1.  int x=0 declares and initialises x to 0

2. x<5 means repeat so long as x<5

3. x++ means increases x by 1 after each loop

so it outputs 0 to 4.

The 3 parts of the for header can be any kind of statement you want. This makes the for statement very flexible and is very often used.

Exercise

Write for loops to output :

1. 0 to 100

2. 0 to 99

3. 20 down to 10

4. 20 down to 10 in steps of 2 ( 20 18 16.. 10 )

5. Can you output 1 to 5, 50 times?

break and continue

These two statements are useful to modify the behaviour of loops.

break; breaks out of a loop. It is usually used with an if. Forexample:

public class Test {

public static void main(String args[]) {for (int x = 0; x < 6; x++) {System.out.println(x);if (x==4) break;}

}}

Without the break, this would output 0 to 5. With the break, it stops at 4.

continue is similar, but just skips the rest of the loop body on that iteration, instead of breaking out of the loop completely. For example:

How To Program © Walter Milner 2013                            Page 29 

Page 30: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

public static void main(String args[]) {for (int x = 0; x < 11; x++) {if (x%2==0) continue;System.out.println(x);}

}}

This loops for x=0,1,2...10. x%2 is the remainder when x is divided by 2, so x%2==0 if x is even.  Because of the if, it skips the print if x is even, and only outputs 1 3 5 7 9.

Random numbers

It is often useful to be able to produce random numbers in a program.

It is theoretically impossible to generate truly random numbers by using a normal computer. The numbers generated must eventually repeat in a sequence. But it is not difficult to make that sequence very long, and we can make pseudo­random numbers. 

Java has a collection of mathematical items in a class named Math. One of these is a method named random, which returns a double in the range 0 to 0.99999:

public class Test {

public static void main(String args[]) {for (int x = 0; x < 11; x++) { // do it 10 timesdouble d = Math.random(); // d is random in range 0 >= d < 1int i=(int)(d*100)+1; // d*100 is in range 0 to 99.99999..// (int).. is a type cast, changing a double to int// (int)(d*100) is in range 0 to 99// (int)(d*100) + 1 is in range 1 to 100System.out.println(i);}

}}

This will output 10 random numbers in the range 1 to 100. 

Adding up

How do you add things up? You start with zero, and every time you get another value, you add it into the running total. For example, to add up 10 random numbers:

double total = 0.0;for (int x = 0; x < 11; x++) {total = total + Math.random();}System.out.println(total);

We have missed out class and main, since you've hopefully got the idea now.

total = total + Math.random();

is a very common kind of action, and can be written:

How To Program © Walter Milner 2013                            Page 30 

Page 31: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

total += Math.random();

Exercise

Add up a sequence of random integers, each in the range 0 to 10. Stop and output the total as soon as it exceeds 100.

Counting

How do you count things? You start from 0, and every time you get something, you add 1. That's it.

Suppose we want to process a sequence of 100 numbers, and count how many are over 0.5. 

int count = 0;for (int i = 0; i < 100; i++) {double number = Math.random();if (number > 0.5)count++;

}System.out.println(count);

Exercise

Modify this so it generates 100 random integers in the range 1 to 10, and counts the even numbers ( if x is even, x%2 == 0. Recall that % gives you the remainder ).

Extreme values

How do we find the largest value in a set of data?

One way is to use the idea of 'the biggest so far'. We go through the data, and when we find one larger than the biggest so far, we change the biggest so far to be this one. We can initialise the biggest so far to be the first one:

double biggestSoFar=Math.random();for (int i = 1; i < 100; i++) {double number = Math.random();if (number > biggestSoFar)biggestSoFar=number;

}System.out.println(biggestSoFar);

Exercise

Modify this so that it also outputs the smallest.

How To Program © Walter Milner 2013                            Page 31 

Page 32: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Square root

Suppose we want to work out the square root of a number in a program. Most languages have a built­in maths library which could do that, and Java does. But how is it programmed? How do you actually calculate a square root?

Here is one way. Suppose we want the square root of X (say,10). Start with a guess, calling it G (say 5). 

Now if G is too big (which it is), then X/G (=2) is too small. 

If G is too small (say 1) then X/G is too big (=10)

Now if one is too big and the other too small, then their average should be better than both.

So have a new guess G = (G+X/G) / 2

And repeat until we are close enough.

Suppose we try this out, to find √10, with a first guess of 5. See how the average becomes the new G on the next row:

G X/GAverage of G and X/G Average squared

5.000000000 2.0000000000000 3.500000000000 12.250000000000

3.5000000000 2.857142857142860 3.178571428571 10.103316326530

3.1785714285 3.146067415730340 3.162319422150 10.000264127712

3.1623194221 3.162235898737390 3.162277660444 10.000000001744

We never get exactly the correct answer. But we can get very close. When to stop? We would like G * G  = X, but it isvery slightly more. We could stop when G2­X is less than some very small amount, say 10­6. 

public class Test {

static double squareRoot(double x){final double ACCURACY=1e-6;double guess = x/2.0;boolean finished=false;while (!finished){guess=(guess+x/guess)/2.0;double temp=guess*guess;if ((temp-x)<ACCURACY)finished=true;

}return guess;}

public static void main(String args[]) {double v=10.0;System.out.println("v = "+v+" root="+squareRoot(v)+ " which squared is "+squareRoot(v)*(squareRoot(v)));}}

In the squareRoot function, we declare ACCURACY to be final – that is, a constant, and we write it in capitals, as a reminder.

The output is 

v = 10.0 root=3.1622776604441363 which squared is 10.00000000174404

How To Program © Walter Milner 2013                            Page 32 

Page 33: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

which is pretty close.

Exercise

1. The square root function has a loop. How many times does it repeat? Modify the program to count, and output, the number of times it loops. Before the squareRoot method, declare a variable

static int counter=0;

Increment counter in the loop, and print it out in main()

2. The algorithm is slower (takes more steps) for larger numbers. Why? Fix it, while keeping the same basic algorithm.

3. Google ways of calculating square roots. Program one youlike.

Euclid's Algorithm

This is another example, which might be called algorithm number 1 – because it is so old. The purpose of this is to find the greatest common divisor (gcd) of two integers.  For example, the gcd of 25 and 15 is 5 ­ this is the largest integer which will divide both 25 and 15 without a remainder. It is named after Euclid, the ancient Greek mathematician who first described it.

To find the gcd of two positive integers a and b:

1. If a is less than b, exchange them

2. Work out the difference r = a­b

3. If r is 0, we have finished, and the gcd is b

4. Otherwise replace a with b, b with r, and repeat from step 1

Here is Euclid's algorithm coded in Java:

How To Program © Walter Milner 2013                            Page 33 

Page 34: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

static int gcd(int a, int b) {int temp, difference;boolean finished = false;while (!finished) {if (a < b) {temp = a;a = b;b = temp;}

difference = a - b;if (difference == 0)finished = true;

else {a = b;b = difference;}

}return b;}

Notice how we have chosen variable names to make this as clear and easy to understand as possible. 

This uses it:

public static void main(String[] args) {int r = gcd(210, 45);System.out.println(r);}

Exercise

Try this out for different values of a and b

Why does it work?

• If a number divides a and b, it also divides a­b ( Suppose the divisor is d, then a=n.d and b = m.d for some integers n and m, so a­b = n.d ­ m.d = d.(n­m) so d divides a­b ). So the gcd of a and b is also the gcd of b and a­b 

• When we replace a and b with b and a­b, the numbers are getting smaller, and one must eventually reach zero (when a=b). When a=b, then b (and a) is the gcd

The usual form of Euclid's algorithm is, instead of replacingthe smaller by the difference, to replace it with the remainder when a is divided by b. For example, suppose a =27 and b=5. Then we make a=5 and b=2. This is simply quicker than repeatedly subtracting 27­5=22, 22­5=17, 17­5=12, 12­5=7, 7­5=2.

How To Program © Walter Milner 2013                            Page 34 

Page 35: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

ArraysThe variables we have seen up to now have all contained a single data value. But there are many situations where we need to handle a set of values. Examples include

• The cheques issued on a bank account

• The pixels across an image

• The employees in a workforce

• The planes in an air traffic control system

We need a structure to hold a set of values. An array is one possibility. Most programming languages offer arrays. Their characteristic features are

• They have a set of values, or elements

• The elements are usually the same type

• The number of elements is fixed at compile­time (when the program is written) and cannot change at run­time

• An element can be accessed using an index. In other words, we can get (or change) the 3rd element, or the 9th, or the 2nd. This is the special defining feature of anarray.

The first element in a Java  array is at index zero.

In this example, we declare an array, put some values in, change some, and output some:

int[] numbers= new int[5]; // get boxes to hold 5 intsnumbers[0]=7; // put 7 in the first boxnumbers[1]=3; // put 3 in the 2nd boxnumbers[2]=5; // put 5 in the 3rdnumbers[3]=7; // put 7 in 4thnumbers[0]=8; // put 8 in the first, over-writing the 7numbers[1]++; // increment the 2nd boxSystem.out.println("At index 0: "+numbers[0]);System.out.println("At index 1: "+numbers[1]);System.out.println("At index 4: "+numbers[4]);System.out.println("At index 0: "+numbers[5]);

which outputs

At index 0: 8

At index 1: 4

At index 4: 0

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

at Test.main(Test.java:29)

At index 0, we put in 7, then over­wrote that with a 8, so weget 8 out. At index 1, we put in 3, then incremented it, so we get 4 out. But what about indexes 4 and 5?

We never assigned a value to numbers[4]. So we get the default value of an int, which is zero.

How To Program © Walter Milner 2013                            Page 35 

Page 36: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

For numbers[5] – it does not exist. The array has 5 elements, but these are indexed 0 to 4. Java checks this at run­time, and if we try to access a non­existent element, weget an exception as shown here.

Arrays and loops

Arrays typically have a very large number of elements, and it is very common to use a loop to deal with them.

For example, this fills an array with 100 random numbers:

final int ARRAY_SIZE = 100;double[] data = new double[ARRAY_SIZE]; // get boxes to hold 100 doublesfor (int index = 0; index < ARRAY_SIZE; index++)data[index] = Math.random();

and this would print them out:

for (int index = 0; index < ARRAY_SIZE; index++)System.out.println(data[index]);

and this would add them up:

for (int index = 0; index < ARRAY_SIZE; index++)total+=data[index];

In this code, we could have used 100 in place of ARRAY_SIZE. So why use ARRAY_SIZE? It is to avoid magicnumbers. The main point is readability. Someone reading

for (int index = 0; index < 100; index++)

would wonder why the 100 was there. But if they see

for (int index = 0; index < ARRAY_SIZE; index++)

it is obvious that the end of the loop is so as to match the length of the array.

The other point is maintainability. If we want to alter this code so that it uses an array of 10000 elements, we just change 1 line:

final int ARRAY_SIZE=10000;

If we had used 100, we would have had to search through all the code and change 100 into 10000, after checking the 100 referred to the size of the array.

Why say final? So that if we go mad and say later

ARRAY_SIZE=28;

the compiler will point out the error to us.

Why say ARRAY_SIZE not arraySize? To remind ourselves that it is constant.

Exercise

Modify this code so the array is just 10 elements long. Then find

How To Program © Walter Milner 2013                            Page 36 

Page 37: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

1. The largest element in the array

2. The smallest

3. The average

For each of these, print out the vales so you can check it is correct.

Sequences

Many simple algorithms are associated with iterating through an array.

For example, suppose we want to output the length of each repeating sequence in some data, and the data value. So if the data is 

7,7,2,9,9,9,3,3,6

we should get 7 2, 2 1, 9 3, 3 2, 6 1

How to do that?

We can track the current data (call it val), and the sequencelength (call it length). We initialise val as the first element, and length to be 1. When we check another value, if it is thesame as val, just increment the length. Otherwise, output val and length, then reset length to 1 and val to be this new value.

Here's the code – which also shows how to initialise an array with some constants:

final int ARRAY_SIZE = 9;int data[]={7,7,2,9,9,9,3,3,6};int val=data[0];int length=1;for (int index = 1; index < ARRAY_SIZE; index++)if (data[index]==val) length++; else{ System.out.println(val+" with length "+ length);

val=data[index]; length=1;}

and the output is:

7 with length 2

2 with length 1

9 with length 3

3 with length 2

Exercise

1. Problem is, that's wrong. Debug it.

2. Alter the code so that it outputs just the longest sequence. With this data, that should be 9.

How To Program © Walter Milner 2013                            Page 37 

Page 38: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Iteration and recursion

These are two key aspects of algorithms. Iteration is repeating ­ a loop. A recursive process calls itself.

Iteration

All non­trivial algorithms involve iteration. Some examples follow.

Find triangle numbers

The triangle numbers are 1, 3, 6, 10, 15.... The nth. trianglenumber is 1+2+3...+n. They are so­called because writing them as dots gives a triangle shape. 

Title : Find the nth triangle number

Purpose : Find a triangle number

Input : A positive number n

Output : none

Return : The nth triangle number

Steps:

A. total ← 0

B. for i in 1 to n

a. total ←total + i

C. return total

In Java:

public class Test {

static int triangle(int n){int total=0;for (int index=0; index<n+1; index++){total=total+index;}

return total;}

public static void main(String args[]) {for (int x=1; x<6; x++)System.out.println(x+" : "+triangle(x));

}}

This is iteration, because of the index loop in the method definition.

Exercise

A triangle number is the sum of an arithmetic progression. Use the formula for this (Google if needed) to write a versionof this which does not use iteration. 

Linear searches

Suppose we have an array:

How To Program © Walter Milner 2013                            Page 38 

Page 39: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

int[] data = { 78, 24, 19, 11, 220, 38, 23, 44, 68, 4, 8 };

and our task is to search for a data item (say 23) and find its location – or possibly find the array does not contain that value.

This is an example of a general task, that of searching a data structure for a value.

The obvious solution is to start at the beginning and look through the array, checking if any value matches:

int lookFor=23;boolean found=false;int location=-1;while (!found && location!=data.length){location++;if (data[location]==lookFor) found=true;}if (found) System.out.println(location);else System.out.println("Not present");

This is an iterative method.

How fast is it? If we are lucky, its the first item in the array. If we are unlucky, it is the last. On average, it will be half­way down.

So if there are n items to search, on average we will take n/2 steps.

Can you think of a faster way?

Recursion

A recursive procedure calls itself. Somewhere in the code of a recursive method, you will find a call to that method.

Tower of Hanoi

In this game, we have three poles, with a set of rings on one. The task is to move all the rings onto another pole, with the rules that

1. You can only move one ring at a time.

2. You can only put a smaller ring on a bigger ring

This is pretty tricky. How about this algorithm sketch:

to move n rings from p1 to p2

if n is 1, just move it and finish

work out which is the third pole p3

move n­1 p1 to p3

move 1 from p1 to p2

move n­1 from p3 to p2  

  

How To Program © Walter Milner 2013                            Page 39 

Page 40: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The idea is we move all but 1 onto the third pole p3, then move the single ring p1 to p2, then move the rest p3 to p2.

We can move a single ring directly.

How do we move n­1? By using this method. And that will use this method again, and so on, but with decreasing n, which will get down to 1, and we can do that directly.

Suppose the poles are labelled A B and C. Here is a version in Java:

static void move(int n, char p1, char p3) {// move n rings from pole p1 to pole p3// easiest case - just 1 to moveif (n == 1) {System.out.println("Move "+p1+" to "+p3);return; // and do nothing more}

char p2='A'; // the other pole. Is it A?if (p1 != 'A' && p3 != 'A')p2 = 'A';

if (p1 != 'B' && p3 != 'B') // or Bp2 = 'B';

if (p1 != 'C' && p3 != 'C') // or Cp2 = 'C';

move(n - 1, p1, p2); // move all but 1, using this method, onto p2move(1, p1, p3); // move the bottom onemove(n - 1, p2, p3); // move the rest from p2 to p3}

}

To test it, try the simplest case:

public static void main(String args[]) {move(1, 'A', 'C');}

outputs

Move A to C

Using 2 rings

move(2, 'A', 'C');

to get

Move A to B

Move A to C

How To Program © Walter Milner 2013                            Page 40 

Page 41: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Move B to C

Other cases are very difficult to check without the game in front of you:

move(3, 'A', 'C');

Move A to C

Move A to B

Move C to B

Move A to C

Move B to A

Move B to C

Move A to C

If the method calls itself, what stops it going on forever? Because

a call with n leads to 2 calls with n­1, so n reduces in the calls, and

the call with n=1 does not recurse, so it will always stop eventually.

Fibonacci sequence

The Tower of Hanoi is a standard example to show recursion. Another is the Fibonacci sequence:

0,1,1,2,3,5,8...

This starts 0,1. Then the next number is the last two added together.

Here is the algorithm:

Title : Fibonacci Purpose : Find the nth Fibonacci numberInput : A non-negative integer nOutput : noneReturn : The nth Fibonacci numberSteps:

A. if n = 0 return 0

B. if n = 1 return 1

C. return fibonacci(n­1) + fibonacci(n­2)

In Java:

static int fib(int n){if (n==0) return 0;if (n==1) return 1;return (fib(n-1)+fib(n-2));}

To test:

public static void main(String args[]) {for (int x=0; x<10; x++)System.out.println(x+" "+fib(x));

}

output:

0 0

How To Program © Walter Milner 2013                            Page 41 

Page 42: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

1 1

2 1

3 2

4 3

5 5

6 8

7 13

8 21

9 34

We can also have an iterative version of this, with no recursion:

static int fib(int n) {if (n==0) return 0;if (n==1) return 1;int current = 0; // the nth Fib, number to be worked outint before1 = 1; // the one beforeint before2 = 0; // two beforefor (int counter = 0; counter < n-1; counter++) {current = before1 + before2;before2 = before1;before1 = current;}return current;}

Exercise

Which is faster? The recursive method has fewer lines – so is it faster? Modify the recursive version so it counts the steps:

How To Program © Walter Milner 2013                            Page 42 

Page 43: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {static int count=0;

static int fib(int n){count++;if (n==0) return 0;if (n==1) return 1;return (fib(n-1)+fib(n-2));}

public static void main(String args[]) {System.out.println(fib(5)+" "+count);

}}

and do the similar for the iterative version (inside the loop). Found out how many steps are involved to calculate the 20th Fibonacci number iteratively and recursively. Explain the difference.

Binary search

Suppose we are searching an array, and the array is sorted:

int[] data = { 4,7,9,10,13,14,18,24,32,45,67,89,98 };

One method would be

• Look at the middle item

• If it matches, finish

• If it is greater, do this again with the lower half

• else do it with the upper half

This is a recursive method.

The method must have parameters marking the lower and upper limits of the range being checked. 

The outline algorithm is very simple, but getting it correct istricky:

static int binary(int[] data, int start, int end, int lookFor){if (start>end) return -1;int middle = (end+start)/2;if (data[middle]>lookFor) return binary(data, start, middle-1, lookFor);else if (data[middle]<lookFor) return binary(data, middle+1, end, lookFor);else return middle;}public static void main(String[] args) {int[] data = { 4,7,9,10,13,14,18,24,32,45,67,89, 98 };int where = binary(data, 0,data.length-1,98);if (where==-1) System.out.println("Not present");else System.out.println("Found at "+where);}

Exercise

Invent a systematic way of testing this, and do so.

How fast is a binary search? 

How To Program © Walter Milner 2013                            Page 43 

Page 44: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

If the item we are looking for is the middle one, we are lucky– we find it in one step. In the worst case we have to keep on halving the intervals until we get down to a range of just 1. How many steps would that be?

Suppose we have 128 items. First step reduces this to a range of 64. Then 32, 16, 8, 4, 2, and 1, when we find it.

So the answer to our question is the same as the number oftimes we can half it until the answer is 1. In other words, for n items, it is the value of d in 2d=n.

That is, log2 n

So the speed of a binary search is around log n.

Suppose we need to search 32768 items. That is 215. So it would take around 15 steps. A linear search would take around 16000 steps. So the binary search is around 1000 times faster. This shows the importance of choosing an algorithm.

Why is it so much faster? In one step on a linear search, we can ignore one item (the one we are looking at – or we've found it). On a binary search, we can ignore half of what remains. So when searching 32768, on the first step we have dealt with 16384 items.

This comes at the cost of having to have the data in order.

  

Equivalence of recursion and iteration

It can be proved that any recursive process can be converted into an iterative one.

Once you have the idea, recursive programs are easy to write. But sometimes, if they repeat identical calculations, they can be slow.

How To Program © Walter Milner 2013                            Page 44 

Page 45: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Data structures

This section gives the idea of what a data structure is, by looking at one example ­ a linked list.

Linked lists

This is the idea of a linked list:

This example has 5 nodes. Each node has two parts ­ some data, and a pointer to the next node.

The data in these nodes are integers, but they could be any type of data. They might also be a collection of fields, like name, address, date of birth and so on. Each node would hold the same set of fields.

These nodes are not in increasing order ( 6 9 3 9 4). If they were, they would be ( 3 4 6 9 9). 

Each pointer would in fact be the address in memory of the next node. But we can think of it as 'pointing to' the next node.

The last node, the tail, has a next pointer which is different ­ since there is no next node for it. The pointer there has a special value, null, meaning 'the pointer to nowhere'. 

Defining a linked list in Java

To do this in Java, we need to set up a new kind of thing – aNode. This concept is the basis of Java – that of object oriented programming. A 'new kind of thing' is a class. We

will define a Node class. Then we will make some instances of the Node class – some Node objects – in other words, some Nodes.

We need to say what data members there are in a Node. There are just two, an int, and a pointer to the next node. We also need a constructor, which is used to create a new node, and a method of linking the node to another one.

Here is our Node class:

How To Program © Walter Milner 2013                            Page 45 

Page 46: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Node {// two data membersint data;Node next;

// the constructor : has same name as the class, no return typeNode(int val){data=val;next=null;}

// method to link this node to anothervoid link(Node another){next=another;}

}

The names of classes in Java should always start with a Capital Letter.

We put this code defining the class in its own file, with a name which exactly matches the class name : Node.java. This means we now have two source code files in our project– Test.java containing main, and Node.java. In Eclipse this 

looks like this.

In main we can make 3 nodes:

How To Program © Walter Milner 2013                            Page 46 

Page 47: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

public static void main(String args[]) {Node node1= new Node(6);Node node2 = new Node(9);Node node3 = new Node(3);}}

We say Node node1 =... because Node is the type. The keyword new invokes the constructor, to create a new 

object.

That gives us:

Now lets link them:

public class Test {

public static void main(String args[]) {Node node1= new Node(6);Node node2 = new Node(9);Node node3 = new Node(3);

node1.link(node2);node2.link(node3);}}

In node1.link...   we are telling the node1 object to do its link method. Check out the dot notation. We always say

<some object>.<some method>(..)

to make a method execute.

But at this stage we just have nodes, and we wanted a linked list. We need another type of thing – another class, named LinkedList:

public class LinkedList {Node head; // One data member, a pointer to the head

LinkedList(Node headNode) // the constructor{head=headNode;}

}

which we can use like this:

How To Program © Walter Milner 2013                            Page 47 

Page 48: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

public static void main(String args[]) {Node node1= new Node(6);Node node2 = new Node(9);Node node3 = new Node(3);

node1.link(node2);node2.link(node3);

LinkedList list1 = new LinkedList(node1); }}

Exercise

Copy this code, and modify it so nodes have 2 data fields, an integer field named  ID and a double field named 'value'. Keep this for the next exercise.

Pretty-printing a linked list

How could we output a linked list nicely like [ 1, 2, 3 ]?

We need to start at the head, printing each node, then follow the pointer on to the next, and repeat until we reach the end. Going through a data structure like this, visiting each node and doing something (like printing it) is called a traversal. 

Here is the class with the print method added:

public class LinkedList {Node head; // One data member, a pointer to the head

LinkedList(Node headNode) // the constructor{head=headNode;}

void print(){System.out.print("[ ");Node nodePtr=head;while (nodePtr!=null){System.out.print(nodePtr.data+" ");nodePtr=nodePtr.next;}

System.out.println("]");}

}

 and to use it:

How To Program © Walter Milner 2013                            Page 48 

Page 49: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {

public static void main(String args[]) {Node node1= new Node(6);Node node2 = new Node(9);Node node3 = new Node(3);

node1.link(node2);node2.link(node3);

LinkedList list1 = new LinkedList(node1);list1.print(); // get [ 6 9 3 ]}}

Exercise

Modify this so it pretty prints your list with two data fields

Adding to a list

Suppose we have a new node, and we want to put it in a 

list, placing it at the head. How do we do that?

We make the next of the new node point to the current headof the list, then change the head to this new node. We need to add a method to the LinkedList class:

How To Program © Walter Milner 2013                            Page 49 

Page 50: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class LinkedList {Node head; // One data member, a pointer to the head

LinkedList(Node headNode) // the constructor{head=headNode;}

void print(){System.out.print("[ ");Node nodePtr=head;while (nodePtr!=null){System.out.print(nodePtr.data+" ");nodePtr=nodePtr.next;}

System.out.println("]");}

void put(int value){Node newNode = new Node(value);newNode.next=head;head=newNode;}

}

tested by:

public class Test {

public static void main(String args[]) {

LinkedList list = new LinkedList(null);list.put(5);list.put(6);list.put(1);list.print(); // get [ 1 6 5 ]}}

Exercise

Write a method called append(), which adds the new node atthe end of the list. You first need to traverse the list to find the last node.

Searching a list

Suppose we want to search a list for a given data item. Usually we would look for some key field, in order to retrieveother value fields linked to that key.  In this example we willjust get the index of the node containing the value, starting at 0. For example if the list is [5, 3, 9] and we search for 9, we should get 2.

If the list does not contain the value, we will return ­1.

How To Program © Walter Milner 2013                            Page 50 

Page 51: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Here its is (this is just the find method, placed in LinkedList.java):

..int find(int val){Node nodePtr=head;int index=0;while (nodePtr!=null){if (nodePtr.data==val)return index;

index++; nodePtr=nodePtr.next;}

return -1;}

Exercise

Add comments to the above method.

Test it.

Deleting a node

To delete a node, we first need to find it. Then we would usually cut it out, by making the next of the previous node point to the following node:

 

In that example, it looks like the 3 node is 'still there'. But ithas been removed from the list. 

We need to be sure the memory used by the node is released and returned to the pool of free memory ­ or otherwise we get a memory leak, and we will eventually run out of free memory if we keep doing it. This depends on the language used. In C and C++ we would need to free the memory. In Java, there would no longer be a reference to the node, and the garbage collector will remove it for us.

If the node to remove is the first one, its slightly different, since then we have to change head to point to the second node. Here it is:

How To Program © Walter Milner 2013                            Page 51 

Page 52: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

void delete(int val) {if (head.data == val) { // is it at the head?head = head.next; // change head to the second nodereturn; // and finish}

Node nodePtr = head; // start searching at the headwhile (nodePtr.next != null) { // until reach the lastif (nodePtr.next.data == val) { // if the next node has valuenodePtr.next = nodePtr.next.next; // cut it outreturn; // and finish}

nodePtr = nodePtr.next; // else go on to next}

}

Exercise

1. We should test this, making sure it can delete the first item in a list, the last, one in the middle, and an item not present. Do this testing.

2. If there are several nodes with the same value, this just removes the first one. Write a method removeAll which would delete all of them.

Ordered Lists

An ordered list has nodes in increasing order ­ or decreasing.

The data in our example lists have just been integers, so it is obvious what 'increasing' means. But suppose the data was name, address and date of birth? They could be in alphabetical order of name, or time order of date of birth, orwhatever. We just need to bear that in mind.

How do we get an ordered list? We start with an empty list, and every time we insert a new node, we have to put it in the correct place. Like this:

How To Program © Walter Milner 2013                            Page 52 

Page 53: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

So, we traverse the list from the head, until we find a node which has data larger than the new node to insert. Then we do the insertion, by making the new node 'next' point to the larger node, and making the previous one point to the new node. This is 'normal' case.

But there are three other situations we must code for:

1. Inserting into an empty list. For that, the head of the list is null. We just change it to point to our new node.

2. The new value is less than everything in the list ­ less than the first node. If so, it should be the new head of the list. So, we make the new node 'next' point to the current head, then change the head to point to the new node.

3. The new value is greater than everything in the list, so it should go after the current last one. We just make the 'next'of the last one point to the new node.

Exercise

Draw diagrams illustrating these 3 cases.

Turning this into Java, we can define a class called OrderedList, which is identical to the LinkedList class, except the put method is altered:

public class OrderedList {Node head; // One data member, a pointer to the head

OrderedList(Node headNode) // the constructor{head = headNode;}

..

void put(int value) {Node newNode = new Node(value);// insertion in empty listif (head==null){head=newNode;return;}

// insertion before headif (head.data>value){newNode.next=head;head=newNode;return;}

// search where to put itNode where=head; // start at the headwhile (true){// if we reach the lastif (where.next==null){where.next=newNode; // put it after the lastreturn;}

if (where.next.data>value) // if next one is bigger{// insert it here

How To Program © Walter Milner 2013                            Page 53 

Page 54: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

newNode.next=where.next;where.next=newNode;return;}

// else go on to nextwhere=where.next;}

}

..}

Code to test this:

OrderedList list = new OrderedList(null);list.put(5);list.put(6);list.put(1);list.delete(7);list.print(); // get [ 1 5 6 ]

Exercise

Modify this so it keeps the list in decreasing order.

Self-organising lists

Searching a linked list for an item is fast if it is near the head, and slow if it is towards the end. 

That means the overall performance will be better if more frequently accessed items are towards the front. One simpleway to do that is to move a node forward one place every time it is accessed. That way the list organisies itself.

The first person to have this idea was McCabe in 1965

Exercise

Implement this in Java. Start with the unordered list, and modify the find method so that a located node is moved forward one place.

Create a list with say 1000 nodes of random integers in the range up to 1000.

Then many times, search for random integers in the range up to 100. This should move smaller numbers towards the front of the list.

Can you show the list gets faster as it is used?

How To Program © Walter Milner 2013                            Page 54 

Page 55: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Object oriented programmingThe previous section used OOP to model linked lists and thenodes they contain. This section provides more features.

A class defines a new type.

The definition is stored in a .java source code file, which is compiled into a .class file. For example, class Node is defined in Node.java, which compiles to Node.class.

By convention, class names should start with a CapitalLetter.

A class has several members – data members (sometimes called fields or attributes), methods (blocks of code which do something) and constructors, which create the instancesof the class.

The order of the definitions of constructors, fields and methods in a class file do not matter. A class cannot be 'run'and its not an executable program. It is a definition. Only inside a method or constructor does the  order of the statements matter.

Packages

A Java application usually contains several classes, which work together to do what is required. In the last section, we saw a LinkedList class using the Node class, since a linked list contains nodes.

Grouping classes together into related groups is useful. A group of related classes is called a package. To create a package called, for example, dataStructures, we just need to:1. say

package dataStructures;

at the start of each class in the package, and

2. Put each file in a folder with the same name.

In Eclipse that looks like:

How To Program © Walter Milner 2013                            Page 55 

Page 56: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Another advantage of using packages is that we do not needto worry if the name of our class clashes with the name of a class somewhere else. The 'fully­qualified' name of our Nodeclass is dataStructures.Node, and this way it has a unique name.

Static and non-static

Class members default to being non­static. For example:

class SomeClass{int x;double y;char z;}

then x y and z are non­static. Every instance of SomeClass (each SomeClass object) has their own x y and z fields, and they will typically be different values for each different instance. Non­static members are per object. We might say

SomeClass obj1=new SomeClass();obj1.x=3;SomeClass obj2 = new SomeClass();obj2.x = 9;

But if we had 

class SomeClass{static int w;int x;double y;char z;}

then the field w is static, which means there is just one value for the whole class. A static member is per class. 

In this example we might say

SomeClass.w = 5;

This is true for methods as well as data fields.

How To Program © Walter Milner 2013                            Page 56 

Page 57: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The starting point for an application, the main method, is static:

public static void main(String args[]) {..

The reason is that execution starts here, and so at this point there are no objects created yet, so we cannot invoke the method on an object. We fix the problem by making the method static, then we do not need to make an object first. 

 

 

How To Program © Walter Milner 2013                            Page 57 

Page 58: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Time and space complexity

Introduction

This section is about comparing different data structures and algorithms, to decide which is the best to use.

It introduces 'big­O' notation used when analysing algorithms

List insertion

We wrote a linked list data structure, and a method to insert a new item at the head of the list. How fast is it? The following code measures how long it takes to insert 1,000,000 new nodes

long start = System.nanoTime();LinkedList list = new LinkedList();for (int count = 0; count < 1000000; count++)list.put(3);

long time = System.nanoTime() - start;System.out.println(time);

System.nanoTime returns the system time in nanoseconds. In fact it took 100092500 ns. Trying that again with numbers of nodes up to ten million, we get the times shownin the  table.

Nodes Time taken (ns)

1000000  10009250

2000000 334951206

3000000 249423751

4000000 553908832

5000000 634907728

6000000 1330103003

7000000 462940693

8000000 1378609484

9000000 1872583335

10000000  1926329984

If we graph this, we get

How To Program © Walter Milner 2013                            Page 58 

Page 59: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

These time measurements have limited accuracy. One issueis that this was run on Ubuntu Linux, which like all modern OS is multi­tasking, so that while this program wasrunning, lots of other things were also running, and they may have changed over different runs. But we will soon see this does not matter.

Suppose we time insertion into an ordered list. This will depend on how big the value to insert is. One way to do it would be to insert random values:

for (int limit = 1000; limit < 11000; limit += 1000) {long start = System.nanoTime();OrderedList list = new OrderedList();for (int count = 0; count < limit; count++){int val = (int)(Math.random()*10000);list.put(val);}

long time = System.nanoTime() - start;System.out.println(time);}

}

Trying this out for up to 10000 nodes we get the graph.

 

Insertion in an unordered list gives a straight line, but an ordered list gives a curve. Why?

Big O notation

This is the code to insert a node at the start of an unordered list:

public void put(int value) {Node newNode = new Node(value);newNode.next = head;head = newNode;}

How To Program © Walter Milner 2013                            Page 59 

Page 60: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

So there are 3 steps involved. If we insert n nodes, that will require 3n steps. If each step takes time t seconds, then

time taken = 3 t n

Now if we ran this on a different computer, with a different clock speed, or a different OS, the time for a single step would be different.

But we are not interested in the speed of a program on one computer. We want the speed of the algorithm with this datastructure. 

In any language, on any computer, 

time taken = some number X n

The value of the number depends on the speed of the computer, which is not what we are interested in. In Big­O notation we say

time = O[n]

meaning the time is proportional to the number of nodes ( and not n2 or log(n) or √n and so on).

Insertion in an ordered list

When a node is inserted in an ordered list, we have to search along the list to find the correct point to insert it.

This might be at the front, or we might be unlucky and it might be at the back, so we have to go all the way through. If there are k nodes, 

the number of nodes could be anything from 1 to k.

If we are inserting random data, there is an equal chance it will be inserted anywhere down the list. On average it will be inserted half way down, or k/2 nodes to check.

That is to insert 1 node. How many to check to insert n nodes? The first is 1/2. The second is 2/2 .The third is 3/2,and so on, with the last being n/2.

So the total nodes to check is

1/2 + 2/2 + 3/2...n/2

=(1+2+3..n)/2

That is the sum of an arithmetic progression, which is n(n+1)/2 (Google if you have not met aritmetic progressions). So the nodes to check is

n(n+1)/4

In big­O, we can ignore the 1/4 factor, since it is a constant, and does not alter how the time depends on n. So the time is

O[n(n+1)] = O[n2+n]

How To Program © Walter Milner 2013                            Page 60 

Page 61: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

but in algorithmic analysis, we are only interested in the time for a large number of data items. We assume that for asmall number of items, all algorithms are fast. The test is how good they are for a large number of items.

This shows n and n2 for different values:

n n2 n2+n

1 1 2

10 100 110

100 10000 10100

1000 1000000 1001000

so for large n, n2 is much bigger than n. So n2+n is almost equal to n2, for large n. So the time of our insertion is

O[n2]

This makes sense. As the list gets longer, it takes on average longer and longer to find where to put it. This is why our graph curves upwards.

In summary, inserting data into an ordered list is slow.

Exercise

This is what happens for random data

1. Suppose the data is inserted in reverse order, with the largest number inserted first, and the smallest last. Where do all the insertions take place? How long to insert n items?

2. Suppose the data is in order, so the smallest is inserted first. Where do all the insertions occur? How long for n?

This is called best­case and worst­case analysis.

How To Program © Walter Milner 2013                            Page 61 

Page 62: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Array data structures

An array is a data structure where the elements can be accessed through an index. That means we can get the third item, or the ninth, or the second.

We show an array of 12 integers. The first element is 7. The second is 9, the third is 1, and so on. We have shown the 

first element as index 0. It is like this in C and Java and Java. Fortran starts at 1.

The following Java code creates an array as above, and outputs the first two elements:

 

int[] array={7,9,1,2,4,7,8,8,2,4,5,1};System.out.println(array[0]); // 7System.out.println(array[1]); // 9

There are only two operations on an array ­ get the value of an element at an index, or change the value at an index.

Standard implementation

In many languages, an array is stored in one contiguous block of memory (not several blocks with gaps between). 

An item is then accessed by an address calculation. Suppose the array starts at address 100, and is made of integers each needing 4 bytes. Where is the third element? There are 2 elements in front of it, in 2 X 4 = 8 bytes. So thethird element is at address 108.

This calculation can be done in constant time, not affected by the size of the array. So the time complexity of array element access is O(1).

Usually then, arrays are fixed in size, and are homogeneous ­ all the elements are the same type.

How To Program © Walter Milner 2013                            Page 62 

Page 63: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Re-sizable arrays

Often we do not know when we create the array how many elements it will have. One solution is to create it with a lot, and hope you do not need more. But that wastes memory if in fact you only use a few elements.

What some languages do is to have a re­sizable array. In Java 'normal' arrays are fixed size, but we can get re­sizablearray as well). When it is created, it has a block larger than the number of elements, to accommodate extra elements.

When sufficient new elements are added, the block becomesfull. A new, larger block of memory is obtained, the data copied to it, and the old block released.  Again the new block is larger than needed, to accomodate additions. Copying the data is slow, so we want to avoid it if possible ­ without using excessive memory.

We show an implementation of this idea in Java, also introducing some more OOP ideas.

Access control, wrapper classes and import

We will define a resizable array class. The idea is that the data is held in a fixed size array with an initial size (of 10). Ifwe try to put something into it beyond the array size, we make a new array twice the size, copy the data to it, and use the bigger array instead. The class will be named ArrayList, and will be part of the dataStructures package.

The first issue is that if we try out the class in Test.java, it has no idea what ArrayList is:

How To Program © Walter Milner 2013                            Page 63 

Page 64: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In fact there is another class called ArrayList, in the package java.util. We can tell Test.java where to look for theArrayList we want, by starting with an import statement:

import dataStructures.ArrayList;

public class Test {

public static void main(String args[]) { ...

We could have done the same by always referring to the fully­qualified class name, dataStructures.ArrayList, but theimport statement saves a lot of typing.

The code for ArrayList is:

package dataStructures;

public class ArrayList {private int capacity;private Integer[] data;

public ArrayList() {capacity = 10;data = new Integer[capacity];for (int i = 0; i < capacity; i++)data[i] = null;

}

private void enLarge() {// create array twice as bigInteger[] newOne = new Integer[2 * capacity];// copy data to itfor (int index = 0; index < capacity; index++)newOne[index] = data[index];

// null the restfor (int index = capacity; index < 2 * capacity; index++)newOne[index] = null;

data = newOne; // switch to the new arraycapacity *= 2;}

How To Program © Walter Milner 2013                            Page 64 

Page 65: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public int size() {return capacity;}

public void set(int index, Integer n) {if (index > capacity)enLarge();

data[index] = n;}

public Integer get(int index) {if (index < 0 || index >= capacity)return null;

elsereturn data[index];

}}

This uses the keywords public and private a lot. Why?

public and private are access modifiers, which are used to achieve encapsulation

A class member marked as public can be used in any other class, including in a different package.  We want other classes to be able to make an ArrayList, so the constructor is public. We also want other classes to be able to put data into an ArrayList, and get it out, so the set and get methodsare public. But we want to stop other classes having direct access to the underlying data, and the capacity field, for 

fear they might accidentally corrupt the values. So we makethem private. This is not a security measure, but an attempt to stop programmers writing bugs. If this data cannot be accessed directly, a bug cannot corrupt it.

The capacity field is private, but we want to allow other classes to know how big the arraylist is, so we have a publicmethod which returns capacity. This makes it in effect a read­only value. A method which reads a private field is called a getter, and one that writes a private field, after validation, is a setter. Getters and setters in general are 

called accessor methods.

If we have neither private nor public, then the default (nothing) setting is package­private. That means the member is visible from within the package, but not outside the package. This expects classes to be packaged so that they will work together, and can directly access each others members, but not from outside, unless they are made public.

Another aspect of this code is that it refers to Integer not int. Integer starts with a Capital Letter, so it is a class. It is an example of a wrapper class, which encloses a primitive (here an int) and which also has some useful methods. Other wrapper classes include Double and Character.

How To Program © Walter Milner 2013                            Page 65 

Page 66: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

We don't we have to import the Integer class? Because it is in the java.lang package, and the compiler looks in there anyway.

We can test our ArrayList by:

import dataStructures.ArrayList;

public class Test {

public static void main(String args[]) {

ArrayList myArray=new ArrayList();myArray.set(5, new Integer(9));myArray.set(2, new Integer(6));myArray.set(12, new Integer(7));for (int i=0; i<myArray.size(); i++){System.out.println(i+" : "+myArray.get(i));}}}

The standard ArrayList in java.util works rather differently, and has a lot more source code.

How To Program © Walter Milner 2013                            Page 66 

Page 67: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Strings

A string is a string of characters – a piece of text. Since humans do so much with writing, strings get special attention in programming.

Java deals with strings in four ways. There is a String class,or you can have an array of char primitives, or you can use the classes StringBuffer and StringBuilder. We will look at each, and pick up some more OOP concepts.  

Unicode

All chars and strings in Java use the Unicode character set.This has a very large number of characters, covering most of the world's written languages, including historic and ancient scripts not used for a thousand years, and many symbol sets. Data can use these, and so can source code. So you can say for example

double π = 3.1415926;double radius=3;double area = π * radius * radius;

 

The charmap utility on Windows and Linux is useful for dealing with Unicode. Note that whether you can see funny characters depends on whether a font is being used which can handle them. 

The String class

Java has a String class, with many useful methods.  For example:

String one="Hello";String two = one.concat(" starts with a SPACE");System.out.println(two);String three=two.toUpperCase();System.out.println(three);String[] words=three.split(" ");for (String s : words)System.out.println(s);

which outputs

Hello starts with a SPACE

HELLO STARTS WITH A SPACE

HELLO

STARTS

WITH

A

SPACE

How To Program © Walter Milner 2013                            Page 67 

Page 68: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The Java API

How do we know all the methods of String? In fact how do we know what classes are available?

There is a standard format documentation available, as the Java API, or application programming interface.

The documentation of String is here.

The documentation of all the Oracle Java classes (version 7)is here 

For each class there is an outline, and a listing of all its constructors and methods.

Objects and references

The String class is immutable. That means you cannot change a String object.

 What about:

String one="Hello";one = "Goodbye";

That looks like we've changed a String. But we have not.

In the code above, 'one' is not a String object. It is a reference to a String object.

The String object “Hello” is held in memory, and 'one' is a reference to it – in other words a pointer to where in memory it is held – probably its address.

When we say

one = "Goodbye";

we do not change any object. We change the pointer to pointto a new object:

String processing

The immutability of strings influences how you should process them. For example, here is a static method to reverse a string: 

How To Program © Walter Milner 2013                            Page 68 

Page 69: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

static String reverse(String s){String result="";for (int pos=0; pos<s.length(); pos++){result=s.charAt(pos)+result;}

return result;}

This goes through the string, from start to end, get each character using charAt, and puts the new character at the front of the result. The last one, which will appear at the front, is the last character in the argument.

So it works. But the result = .. creates lots of intermediate String objects – one for each character. A more efficient alternative is to use StringBuilder:

static String reverse(String s){StringBuilder result=new StringBuilder("");for (int pos=0; pos<s.length(); pos++){result.insert(0, s.charAt(pos));}

return new String(result);}

A StringBuilder is like a String, but mutable. It is common to make a StringBulder object, modify it, then return a String constructed from the StringBuilder instance.

StringBuffer is similar but is thread­safe and slower.

Comparing objects and references

A palindrome is the same when reversed. So 'aoxomoxoa' is a palindrome.

One way to tell if a string is a palindrome would be to reverse it, and to see if it is the same. So we might say:

static boolean isPalindrome(String s){String r = reverse(s);return s == r;}

but if you test it, this does not work – it always gives false. Why?

In this code, s is not a String object. It is a reference to a String object. Same for r. So s == r checks if these two references are the same – in other words, if they point to thesame object – which they do not.

Clearly r and s do not point to the same object. What we want to know is whether those two objects contain the samecharacters. The .equals() method does that:

How To Program © Walter Milner 2013                            Page 69 

Page 70: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

static boolean isPalindrome(String s){String r = reverse(s);return s.equals(r);}

This works as expected. .equals is a method of String, which returns true if the other String contains the same sequence of characters.

All classes, not just String, have an equals method.

How To Program © Walter Milner 2013                            Page 70 

Page 71: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Sort algorithms

The sort concept

To 'sort' data means to arrange it into order.

For example, if we sort

[ 7 4 8 3 5 ]

into increasing order we get

[ 3 4 5 7 8 ]

We could also sort into decreasing order. If the data is not numeric, then 'order' has some other meaning. If it is text, we might use dictionary order.

The reason why it is called 'sorting' is interesting. Why is it not called 'ordering'? To 'sort' something means to separate it into different 'kinds'. Why is that connected with putting things in order?

In 1890 Hollerith (who went on to found IBM) processed thedata from the US Census, using punched cards. The cards were passed through a machine and separated using an algorithm called a radix sort. This works as follows:

Separate the cards into 10 piles, onthe basis of the first digit. So the firstpile is all 0something, the second is all1something, the third is 2something

Take each of these, and separate into10 piles on the second digit. So one ofthese set of ten would be 10.., 11..,12.... 19

Separate these on the third digit, for100.., 101.., 102...

Continue to the last digit. 

Put all piles back together. They arenow in order.

This is why 'sorting' came to mean 'ordering'.

In base 10 numbers, each stage generates 10 piles. But on a computer the data is binary, and we just have 2 piles ­ for0 and 1. Processors also have single machine code instructions to test for a single bit. This means a radix sort is extremely fast ­ quicker than a quicksort, which we will meet shortly and is the most common algorithm in use now.It is strange that the first algorithm is faster than usual onein current use. We will code radix sort in a later section.

How To Program © Walter Milner 2013                            Page 71 

Page 72: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Bubble sort

There are many different sort algorithms, and they vary greatly in speed. It is usual to start with a bubble sort.

Suppose we go through a list of numbers and swap each number and the next if they are in the wrong order. For example:

9 8 10 6 7 1 7 swap

8 9 10 6 7 1 7 no swap

8 9 10 6 7 1 7 swap

8 9 6 10 7 1 7 swap

8 9 6 7 10 1 7 swap

8 9 6 7 1 10 7 swap

8 9 6 7 1 7 10 final state

At the end the largest number, 10, has been swept to the end. But the rest are not yet in order. The second largest, 9,has only been moved up one place. 

If we did this a second time, the second largest number, 9, would move to its final place, one from the end.

If we did it a third time, the third largest, would move to its correct position.

If there are n numbers, we must therefore do this n times, to get them all in the correct position:

1. repeat n times:

2. go through the list from start to end, and swap adjacent values if they are in the wrong order  

Here it is in Java:

final int SIZE = 10;double[] data = new double[SIZE];// fill array with random numbersfor (int index = 0; index < SIZE; index++)data[index] = Math.random();

// do bubble sortint end = SIZE - 1;for (int time = 0; time < SIZE; time++)for (int index = 0; index < end; index++) {if (data[index] > data[index + 1]) {double temp = data[index];data[index] = data[index + 1];data[index + 1] = temp;}

}// display array contentsfor (int index = 0; index < SIZE; index++)System.out.println(index + " : " + data[index]);

which outputs something like:

0 : 0.3411649943934846

1 : 0.4123942855959868

2 : 0.4207890477857321

3 : 0.6273373150343701

4 : 0.6918709783394186

How To Program © Walter Milner 2013                            Page 72 

Page 73: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

5 : 0.7042990335581902

6 : 0.7152050462793944

7 : 0.8710305428710455

8 : 0.9235170851394418

9 : 0.9589815770978095

We can improve bubble sort, to make it faster, in several ways. To put n items in their correct place, we only need to do it n­1 times, since if n­1 values are in the right place, thelast one must be also.

Exercise

Alter the code to do this (time only needs to go up to SIZE­1)

After the first pass, the largest number has been moved to the end.

So on the second pass, we do not need to go so far. We can finish the second pass one from the end.

We can finish the third pass two from the end. Finish the fourth pass three from the end.

So in our Java version, we can decrease 'end' after each pass.

Exercise

Alter the code to do this ( end­­; at the correct point )

Suppose we use this method on

[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

in other words on data which is already sorted. It will still go through the same process and take just as long, even though there is nothing to do.

We can fix this by having a boolean flag which represents whether any pair was switched in one pass. We make it false before each pass, and change it to true if we do a swap. If it is still false after a pass, the data is already sorted and we can stop.

Exercise

Alter the code to do this. Use break to break out of the outerloop.

Bubble sort is stable and in place

Suppose we have 2 equal numbers  in the list. What will happen to them? We say

How To Program © Walter Milner 2013                            Page 73 

Page 74: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

if (data[index] > data[index + 1]) {

We swap them if one is bigger. If they are equal, we do not. That means two equal values remain in the same order. That means the sort is stable.

It also uses no extra storage, apart from the temporary variable and the counters. The numbers in the list are re­arranging still in the list. We do not move them to anotherdata structure. That means bubble sort is in place. For large data sets this is an issue ­ if we are sorting megabytes of data, we would like to avoid copying it into additional megabytes if possible.

Time complexity of a bubble sort

The worst case for a bubble sort is if the data is initially in reverse order. In that case, for n items, n­1 passes are required. The length of each pass is n­1, then n­2,  then n­3, down to 1. This averages n/2, and the total number of comparisons is

(n­1) n/2 =O(n2­n) = O(n2)

For random data the number of swaps will be less, but it will still be O(n2)

The best case is if the data is already sorted, and we use theimprovement given we only need to go through it once and the time is O(n)

For small numbers of items to sort (say 100 or less) a bubble sort is OK ­ but then for that number, any method isOK. For more than a 1000,  it takes more than a million steps, and it is usually too slow.

Quicksort

There are many other sortalgorithms. We will look at justone other ­ the commonly usedquicksort, invented by TonyHoare in 1960. 

The idea is as follows:

Choose one element ­ say theone on the right ­ to be the'pivot value'. Go through thearray left to right. If we meet anitem less then the pivot, swap it with a growing section of small items at the left:

How To Program © Walter Milner 2013                            Page 74 

Page 75: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

left right = pivot

60 40 31 70 10 50

60 40 31 70 10 50 swap

40 60 31 70 10 50 swap

40 31 60 70 10 50

40 31 60 70 10 50 swap

40 31 10 70 60 50

less than pivot equal or more than pivot

When we reach the right, everything less than the pivot has been moved to the left. This means we have partioned the array into two parts. The left part is all less than something,and the right part is all equal or more than something. So we recursively do this again on the two parts, until the parts get down to length 1.

Here is a version in Java. First one partition stage:

static int partition(int[] array, int left, int right, int pivotIndex) {int pivotValue = array[pivotIndex];int temp = array[right];array[right] = array[pivotIndex];array[pivotIndex] = temp;int storeIndex = left;for (int i = left; i < right; i++) {if (array[i] <= pivotValue) {temp = array[i];array[i] = array[storeIndex];array[storeIndex] = temp;storeIndex++;}

}temp = array[storeIndex];array[storeIndex] = array[right];array[right] = temp;return storeIndex;}

used in the sort:

static void quicksort(int[] array, int left, int right) {if (left < right) {int pivotIndex = (left + right) / 2;int pivotNewIndex = partition(array, left, right, pivotIndex);quicksort(array, left, pivotNewIndex - 1);quicksort(array, pivotNewIndex + 1, right);}

}

started off by

How To Program © Walter Milner 2013                            Page 75 

Page 76: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

final int SIZE = 30;int[] data = new int[SIZE];for (int i = 0; i < SIZE; i++)data[i] = (int) (Math.random() * 1000);

quicksort(data, 0, SIZE - 1);for (int i = 0; i < SIZE; i++)System.out.println(data[i]);

How fast is it? Firstly, let's think about initially random data. How many levels of recursion will there be? Each one halves the array (on average). So how many times can you divide n by 2 until you get to 1? For example if n is 64, you get partitions of size 32, 16, 8, 4, 2, 1. That's 6. In general, it is log2n.

Now for each level of partition ­ how many elements in the array do we scan through? All n of them. And we do that log2n times. So for random data quicksort is O(n log n). Comparing this with bubblesort's O(n2):

n n log n n2

10 33.21928095 100

100 664.385619 10000

1000 9965.784285 1000000

10000 132877.1238 100000000

100000 1660964.047 10000000000

1000000 19931568.57 1E+12

So for large n, n2 is much bigger.

The sort function provided in the libraries of many languages is quicksort.

Suppose the data is already sorted? What will quicksort do?On a partition, the item on the right is the only one which isequal or greater than it. So the split will be between the right­most one, and the rest. The number of partitions will be n, and the time will be n2  ­ a disaster. An obvious improvement is an initial check for ordered data.

Exercise

In a selection sort, we find the smallest element in the array, and swap it to the front. Then we find the next smallest, and swap it to position two, and so on.

Write a selection sort in Java. Test it. Work out the best andworst case time complexity. Measure it.

Exercise

If you have a sense of humour, Google bogosort and program it.

How To Program © Walter Milner 2013                            Page 76 

Page 77: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Stacks

A stack is a linear data structure, and we can do two thingswith it ­ push a value onto the stack, and pop a value off it:

We can only push a value on the 'top', and only pop off the top. That means the value we get when we pop a value will be the last one we pushed on. For this reason a stack is often called a LIFO structure ­ last in, first out.

Linked list implementation

How can we actually implement a structure which works like this? One way is to use a linked list, as coded in Java ina previous section. Our stack will contain a linked list, and we just need to write push and pop methods.

package dataStructures;

public class Stack extends LinkedList {

public void push(int val){put(val);}

public int pop(){int val=head.data;head=head.next;return val;}}

which would be used as

Stack stack = new Stack();stack.push(1);stack.push(2);stack.push(3);System.out.println(stack.pop()); //3System.out.println(stack.pop()); //2System.out.println(stack.pop()); //1

OOP inheritance

Our Stack is like a LinkedList, except that it has two extra methods – push and pop. We could have copied the code of LinkedList, pasted it into Stack.java, and added the two extra methods. Instead we said:

public class Stack extends LinkedList {

This uses the OOP idea of inheritance.

How To Program © Walter Milner 2013                            Page 77 

Page 78: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The idea is that one class can inherit from another class. In this example, LinkedList is the base class, and Stack is the sub­class. We would say we have 'sub­classed' LinkedList. When one class sub­classes another:

1. All data members of the base class and all methods are inherited by the sub­class. In other words, the sub­class has all the data members are methods of the base class.

2. The sub­class can define extra members. This happened in our example – Stack has the extra pop and push methods.

3. A sub­class can over­ride methods of the base class. That means, the sub­class can define methods with the same name and return type as in the base class, and these will be used by the sub­class, instead of the base class version.

4. Constructors are not inherited.

We will discuss inheritance more later.

Exercise

Some stack implementations have a peek() method, which returns the top of stack, but leaves the item on the stack and does not remove it. Write the peek method. Consider what to do when peeking at an empty stack. 

Uses of stacks - reversing things

If we push 7 and 3, we pop 3 and 7. So we can use a stack to reverse things:

Stack stack = new Stack();int[] data = { 1, 2, 3, 4, 5 };for (int i : data)stack.push(i);

for (int index = 0; index < data.length; index++)data[index] = stack.pop();

for (int i : data)System.out.println(i); // 5 4 3 2 1

Uses of stacks - return address

Here is some Java code:

How To Program © Walter Milner 2013                            Page 78 

Page 79: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The path of execution is these line numbers:

16, 8,10, 3, 5, 11, 17

When fun1 returns, it goes back to line 17.

When fun2 returns, it goes back to line 11

How does return 'remember' where to return to? By using a stack. When a function is called, the next line number is pushed on a stack. At a return, the stack is popped, giving the line number to return to. Like this

Line number

Action Stack ­ top to the right

16 call fun1 17

10 call fun2 11 17

5 return ­ pop11 17

11 return ­ pop 17

17 Output and end

This means we can have an unlimited depth of function calls, and it all works.

Unless you ask for an infinite stack:

static void fun1(){fun1();return;}

which produces

Exception in thread "main" java.lang.StackOverflowError

at Test.fun1(Test.java:10)

at Test.fun1(Test.java:10)

at Test.fun1(Test.java:10)

at Test.fun1(Test.java:10)

at Test.fun1(Test.java:10)

at Test.fun1(Test.java:10)

How To Program © Walter Milner 2013                            Page 79 

Page 80: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

at Test.fun1(Test.java:10)

In fact the stack is usually (in most languages) used to passparameters as well as to track return addresses. When a function is called, the return address is pushed, then the parameters. At the start of function execution, the parameters are popped off the stack. Then at the end, the return address is popped.

Uses of stacks - expression evaluation

Suppose you want to write program code which will evaluate a string. So "1 + 2" evaluates to 3.

The obvious way is to traverse the string left to right, and work it out as you go. This won't work, since when you get to +, you do not know what to add the 1 to. Further, if the string is "1+2*3" then the multiplication must be done before the addition.

One way to do it is using an operator precedence parser, as follows. Have two stacks ­ opStack for operators +and *   and valStack for values. And two actions ­ shift pushes ontoa stack, while reduce pops two values off valStack, applies the operand to them, and pushes the result back onto valStack. 

The input is scanned left to right. Values are shifted onto the valStack. For operators, use the following table to decidewhat to do:

Scanned input symbol

+  *

Top of opStack

+ reduce shift

* reduce reduce

empty shift shift

  At the end, the value is the single value on the valStack.

 Example with 2*3+4*5:

valStack (top on right)

opStack input action

empty empty 2 shift

2 empty * shift

2 * 3 shift

2 3 * + reduce

6 empty + shift

6 + 4 shift

6 4 + * shift

6 4 + * 5 shift

6 4 5 + * empty reduce

6 20 + empty reduce

26 empty empty end

How To Program © Walter Milner 2013                            Page 80 

Page 81: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Exercise

Code this in Java

Uses of stacks - programming languages

Some languages use a stack as a primary basis for holding data. One example is the language Forth. Another is Java bytecode. In Java, source code is compiled into bytecode, and the bytecode is executed by the Java Virtual Machine. Here is some Java source code:

x = 5;

y = 3;

z = x + y;

and this is the bytecode it compiles into:

0: iconst_5 // push 5 on the stack 1: istore_1 // pop value off stack into variable 1 2: iconst_3 // push 3 on stack 3: istore_2 //pop stack into variable 2 4: iload_1 // get variable 1 (x=5) 5: iload_2 // get variable 2 (y=3) 6: iadd //add them 7: istore_3 // store result in variable 3 (z)

Exercise

Google Charles H. Moore

Time Complexity

As normally implemented with a linked list, a push or a popis a single step, if we do it at the head of the list. So they areconstant O(1). Pushing or popping a value off a stack takes a fixed amount of time, irrespective of the number of items on the stack.

Exceptions

What would happen if we popped a value off an empty stack? What do we want to happen?

The normal situation is that we pop a value off. The exceptional situation is when the stack is empty. Most languages including Java have a way to deal with exceptions. Two common examples of exceptions are trying to open a file which cannot be found, and a user enters an invalid number, say with two decimal points.

There is a class named Exception, and instances of this model the occurrence of an exception. When an exception occurs, the code has two choices – to 'deal with' or 'handle' the exception, or to 'throw' it, which means some other codewill need to handle it. If no other code does, the application will end. But this should only be allowed to happen in thoserare cases when it is logically impossible to handle the exception. 

How To Program © Walter Milner 2013                            Page 81 

Page 82: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In our case, we first need to define an appropriate exceptionclass, which we can do simply by subclassing RuntimeException:

package dataStructures;

public class StackUnderflowException extends RuntimeException {

public String getMessage() {return "Stack empty";}

}

Then we modify our stack pop method:

public int pop() throws StackUnderflowException{if (head==null) throw new StackUnderflowException();int val=head.data;head=head.next;return val;}

which we could use like this:

Stack stack = new Stack();stack.push(1);stack.push(2);stack.push(3);try{while (true)System.out.println(stack.pop());}

catch (StackUnderflowException su){System.out.println("The end");}

The try.. catch control structure means:

try{.. some code which might throw an exception..}catch (SomeException e){.. code to execute if the exception happens..}

More on inheritance

Suppose we have a base class and a sub­class:

How To Program © Walter Milner 2013                            Page 82 

Page 83: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

class BaseClass{int x;BaseClass(int val){x=val;}void baseMethod1(){System.out.println("In base method1");}void baseMethod2(){System.out.println("In base method2");}}class Sub extends BaseClass{int y;Sub(int val){x=val+1;}void baseMethod2(){System.out.println("In sub method2");}void subMethod1(){System.out.println("In sub method1");}

}

Then

1. Sub has a data field called x, and a method called baseMethod1. It has inherited these from BaseClass.

2. Sub has an additional field, y, and an additional method subMethod1

3. Sub has a method, baseMethod2, with the same name asin BaseClass. This method over­rides the base class version.

So we can say

Sub s = new Sub(3);s.x=7; // inherited data members.baseMethod1(); // inherited methods.baseMethod2(); // use new over-ridden versions.subMethod1(); // use new method

or, we could if it would compile. It won't because of constructors.

When you write a constructor, you can call super(); as the first statement:

Sub(int val){ super(); x=val+1;}

super(); calls the constructor of the base class, and it creates the stuff the sub­class will inherit.

Super() calls the 'no­arg constructor' – the constructor with no arguments. If you said super(3) it would have called the  constructor which takes an int argument.

If you do not say super(); the compiler puts it in for you (in the bytecode it generates). 

How To Program © Walter Milner 2013                            Page 83 

Page 84: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

That is what is happening in our example.

And that is the syntax error – BaseClass does not have a no­arg constructor. 

There are two solutions

1. Write a no­arg constructor for BaseClass, or

2. Put super(val); at the strat of the Sub constructor.

What is the point of inheritance?

It is not essential. C is an excellent programming language, and has no inheritance ( because it does not have classes ). But it is useful in two ways

1. It corresponds to the way we think about categories. A Car is a type of Vehicle. A Ford is a kind of car. A Focus is atype of Ford. Since Aristotle wrote his Categories, people have thought this way.

2. It allows for code re­use. We often want a kind of thing, and we already have a similar class, but we want to change it a bit. So we sub­class it. This is much more efficient than starting again from scratch.

The Object class

What about

class BaseClass

Does it extend any other base class in turn?

The answer is, yes. It does not say extends Anything, but in fact it extends a class called Object.

Object is the ultimate base class of all other classes. All classes descend ultimately from Object.

Object has few methods – like .equals and .toString and .hashCode. The idea is to ensure that all classes inherit these methods. Often they are over­ridden with new versions in sub classes.

If you look at the API of a class you see the inheritance hierarchy:

 

How To Program © Walter Milner 2013                            Page 84 

Page 85: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

A JFrame models a GUI window, and is in the package javax.swing. This inherits from java.awt.Frame, then from Window, and so on back to Object, in java.lang.  A JFrame inherits all the methods of those preceding classes.

How To Program © Walter Milner 2013                            Page 85 

Page 86: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Abstract Data Types

An abstract data type (ADT)  defines a type of data purely interms of how it behaves.

As an example, a stack is an ADT with just two operations:

• Put a data item into a stack (normally called push)

• Get a data item out (called pop) in such a way that the item is the last item which was put in

To implement an ADT in some actual programming language, we also need to find

• Some data structure to represent the ADT

• Algorithms to carry out the operations

In the case of a stack, we can use an array, or a linked list. The algorithms to carry out the operations  will depend on the choice of data structure, but in the case of a stack, theyare trivially simple.

A formal approach to this subject uses these ideas ­ an ADT, a representation and a set of algorithms.   

How To Program © Walter Milner 2013                            Page 86 

Page 87: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Queues

A stack is a linear structure where data is added and removed at the same end (LIFO). By contrast, a queue is a linear structure where data is added at one end, and 

removed from the other. That means it is first in first out, orFIFO.

Operations

We can just do two things with a queue:

A. enqueue a new item (add data to the queue)

B. dequeue an item (remove data from the queue)

Implementation - Linked List

How to make such a thing?

One way is to use a linked list.  We need access to both the head and the tail of the list, so it is faster to maintain pointers to both (rather than traversing the list every time tofind the tail). Also when dequeueing from the tail, we need to 'go back' so it is convenient to use a double­linked list. Enqueueing is like this:

and dequeing is:

How To Program © Walter Milner 2013                            Page 87 

Page 88: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

An implementation in Java is:

package dataStructures;

public class Queue {private class Node{int data;Node previous;Node next;Node(int val){data=val;next=null;previous=null;}

}

Node head;Node tail;

public Queue(){head=null;tail=null;}

public void enQueue(int val){Node newNode= new Node(val);if (head==null){head=newNode;tail=newNode;return;}

newNode.next=head;head.previous=newNode;head=newNode;}public int deQue(){int val=tail.data;

How To Program © Walter Milner 2013                            Page 88 

Page 89: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

tail=tail.previous;return val;}}

which we can try out as

Queue q = new Queue();q.enQueue(1);q.enQueue(2);q.enQueue(3);System.out.println(q.deQue());System.out.println(q.deQue());System.out.println(q.deQue());

which outputs 1 2 3 as expected

Inner classes

In this implementation, the Queue class uses instances of the Node class as its doubly­linked nodes. However the Node class is not defined in a separate Node.java file. It is defined inside the Queue class. This makes it an inner class.

It is also private. As for other members, this means it is only visible from Queue.

The idea behind this is that we are supposing that the doubly­linked Node will not be used by any class other thanQueue. Then making it a private inner class means we maintain the encapsulation of Queue, and do not clutter thedatastructures package with an additional class/file. If Node had not been inner (had been a top level class) this would still have worked, but not been so tidy.  

Exercise

There would be a problem if you tried to deque an empty queue. An obvious tactic would be to have it throw a QueueUnderflowException. Implement this (see the stack version).

How To Program © Walter Milner 2013                            Page 89 

Page 90: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Implementation – Array

How To Program © Walter Milner 2013                            Page 90 

Page 91: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In languages with fixed length arrays, we can use one to implement a queue. Since the elements are next to each other, we do not need pointers. We need indexes to track 

the head and tail of the queue, which may need to wrap around.

It is important to be clear what 'head' and 'tail' denote here. Head is the index of the array element in which the next valuewill be enqueued. If that element has a value in it, it will be over­written. Head is not in the queue. It is the first item not in the queue.  Tail is the index of the element which we get if we deque. Tail is the last item in the queue. 

Exercise

Implement and test a queue in Java using an array. It starts:

package dataStructures;

public class Queue {final int SIZE=100;int[] data = new int[SIZE];int head=0;int tail=0;

You need to write enqueue and dequeue methods, and workout how you tell if the queue is empty, and full..

How To Program © Walter Milner 2013                            Page 91 

Page 92: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Priority queues

In a priority queue, the data items include a 'priority' field, and nodes are kept in order of decreasing priority. As a result, when a value is dequeued, it will be the one from thehead, with the highest priority. (or we could keep it in increasing order, and deque from the tail).

To implement that as a linked list, we need an additional field in the nodes for priority.

We have an ordered singly linked list, ordered on the priority field. This starts:

package dataStructures;

public class PriorityQueue {

private class Node{int data;int priority;Node next;Node(int val, int p){data=val;next=null;priority=p;}}

Node head;

public PriorityQueue(){head=null;

}

The enqueue method has most code:

How To Program © Walter Milner 2013                            Page 92 

Page 93: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public void enQueue(int val, int priority){Node newNode= new Node(val, priority);if (head==null) // insertion in empty q{head=newNode;

return;}

if (head.priority<=priority){ // insertion before current headnewNode.next=head;head=newNode;return;}

Node where=head;while (true) // move along the list{ // if we reach the end..if (where.next==null){where.next=newNode;

return;}

// if we meet a smaller one..if (where.next.priority<=priority){newNode.next=where.next;where.next=newNode;return;}

}}

and dequeue is simpler:

public int deQue(){Node where=head;if (head.next==null) // last one{head=null;}

else{head=head.next;}

return where.data;}

Exercise

1. This ignores dequeing an empty queue. Fix this.

2. Use this to insert 100 items with random priority, then dequeue them.

3. They will be retrieved in order of priority, so this is a sort.What is its time complexity?

Namespaces

The code for the PriorityQueue refers to the Node class. So does the code for the Queue class. How come they refer to the correct Node class? Because they are in different namespaces.

How To Program © Walter Milner 2013                            Page 93 

Page 94: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In Computer Science a namespace is a way of limiting 'where' a name has a meaning. Without namespaces, we could only have one variable named 'x' in an entire application. In practice we can have lots of 'x's, so long as they are in different namespaces. The way that namespaces are implemented varies between languages.

In Java, namespaces are maintained through packages, classes, inner classes, methods and blocks.

So for example, we can distinguish our PriorityQueue from others (like the one in java.util) because its fully qualified name is dataStructures.PriorityQueue. The import statement simply avoids having to type that every time.

The class further divides a namespace. So Maths.PI is the name of the static data member PI in the class Maths. We could have a class named MyMaths, with a value MyMaths.PI – although it is hard to think why.

Namespaces control the names of things. Access modifiers control their visibility. So for example the inner classes Queue.Node and PriorityQueue.Node have different names. But they are also declared as private, so they are not visible outside their classes anyway.

How To Program © Walter Milner 2013                            Page 94 

Page 95: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Generics

Two ideas work in opposite directions – strong typing and algorithms. Generics fixes the problem.

Java is a strongly typed language. That means whenever you declare a variable, you must say what type it is. This is a good thing.

But as we have seen, algorithms are typeless. The quicksortalgorithm is the same whatever the type of data. The algorithm to delete an item from a linkedlist is the same no matter what type of data is in the list. However whenever wewrite Java code, we must say what the type is. 

That would mean we have to write a linked list for integers, another one for strings, another for double, and so on. There is no way to re­use the same code for different data types. Except for generics.

It generic programming, you have type parameters in the code. To use the code, you supply a type as a value for the type parameter. And you get a version of the code appropriate for the type you want.

Writing generic code is sometimes tricky. But much of the time we can use the Collections framework, which provides generic code for the standard data structures, and is very easy to use.

A generic linked list

We can modify the code given earlier, to define a linked list which will hold any reference type, not just ints. We start with a node which can hold any type:

How To Program © Walter Milner 2013                            Page 95 

Page 96: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

package dataStructures;public class GenNode <T>{T data;GenNode<T> next;

// the constructorGenNode(T val){data=val;next=null;}

// method to link this node to anothervoid link(GenNode<T> another){next=another;}

}

The <T> is a type parameter. It does not need to be T, but this is the convention. Whenever we actually make a GenNode, we have to specify what T is. We use this in a generic linked list:

package dataStructures;

public class GenLinkedList <T>{GenNode<T> head; // One data member, a pointer to the head

public GenLinkedList() {head = null;}

public GenLinkedList(GenNode<T> headNode) {head = headNode;}

public void print() {System.out.print("[ ");GenNode<T> nodePtr = head;while (nodePtr != null) {System.out.print(nodePtr.data + " ");nodePtr = nodePtr.next;}

System.out.println("]");}

public void put(T value) {GenNode<T> newNode = new GenNode<T>(value);newNode.next = head;head = newNode;}

public int find(T val) {GenNode<T> nodePtr = head;int index = 0;while (nodePtr != null) {if (nodePtr.data.equals(val))return index;

index++;nodePtr = nodePtr.next;}

How To Program © Walter Milner 2013                            Page 96 

Page 97: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

return -1;}

public void delete(T val) {if (head.data.equals(val)) { // is it at the head?head = head.next; // change head to the second nodereturn; // and finish}

GenNode<T> nodePtr = head; // start searching at the headwhile (nodePtr.next != null) { // until reach the lastif (nodePtr.next.data.equals(val)) { // if the next node has

valuenodePtr.next = nodePtr.next.next; // cut it outreturn; // and finish}

nodePtr = nodePtr.next; // else go on to next}

}

}

This is the same as the non­generic linked list, except that there we used int instead of T, and == in place of .equals.

We can use this then for any reference type:

GenLinkedList<Integer> numbers = new GenLinkedList<Integer>();numbers.put(3);numbers.put(2);numbers.put(5);numbers.print();GenLinkedList<String> words = new GenLinkedList<String>(); // [ 5 2 3 ]words.put("go");words.put("we");words.put("Here");

words.print(); // [ Here we go ]

T must be a reference type, not a primitive, so we must say GenLinkedList<Integer> not GenLinkedList<int>, and this code uses 'auto­boxing', since

numbers.put(3);

is actually

numbers.put(new Integer(3));

The Java Collections framework

This is a set of interfaces and classes which provide generic implementations of all the standard data structures and associated algorithms. Check the Oracle documentation for full details. 

How To Program © Walter Milner 2013                            Page 97 

Page 98: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

For example, we might need to use a set of Strings, but we do not know how many, so we cannot use a String array. We could define our own linked list or re­sizable array, but we do not have to since we can use java.util.ArrayList instead:

ArrayList<String> words = new ArrayList<String>();words.add("The");words.add("small");words.add("black");words.add("cat");System.out.println(words.contains("Cat")); // falsewords.remove("small");for (String s: words)System.out.print(s); // Theblackcat

Another useful collection is a HashMap. This is a set of key­value pairs. You can put key­value pairs into it, retrievea value with a given key, get all the keys and so on:

HashMap<Integer, String> map = new HashMap<Integer, String>();map.put(5, "Green");map.put(1, "Blue");map.put(7, "Red");map.put(2, "Orange");System.out.println(map.get(7)); // RedSystem.out.println(map.get(3)); // nullSet<Integer> keys = map.keySet();for (Integer i : keys)System.out.println(i); // 1 2 5 7

The Collections are good illustrations of the idea of abstraction. How does HashMap work? We don't know, other than it is based on a hash table. Does it matter how itworks? No. If Oracle changes the way it works, does it matter? No. If you want to know, look at HashMap.java. 

Radix sort

We can illustrate the use of an ArrayList to implement a radix sort.

Suppose we want to sort an array of words, each containing10 random letters.

Using a radix sort, as used by Hollerith in 1890, we

1. Separate them into 26 piles, according to the last letter

2. Put the piles together (keeping the sequence unchanged), then separate them again on the basis of the second to last letter

3. Repeat 1 and 2 until we put them together on the basis ofthe first letter

We will do this in Java.

We need to make the array – which means we need to be able to generate random letters of the alphabet.  This generates random letters with character codes in the  range 'from' up to 'to' inclusive:

How To Program © Walter Milner 2013                            Page 98 

Page 99: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

static char rand(int from, int to){return (char) ((int)(Math.random()*(to-from+1))+from);}

Exercise

1. Test this

2. Work out how it works

Once we can get random letters, we need to make an array of strings of random letters:

static String[] makeRandomWords(){final int wordCount=10;final int letterCount=10;String[] words = new String[wordCount];for (int index=0; index<wordCount; index++){words[index]="";for (int letter=0; letter<letterCount; letter++){words[index]=words[index].concat(""+new

Character(rand('A','Z')));}

}return words;}

In this, the char literals 'A' and 'Z' are cast implicitly to theirint values (65 and 90).

To display the words, we can use:

static void print(String[] words){for (String s : words)System.out.println(s);

}

Now we need the actual sort:

static String[] radixSort(String[] data) {ArrayList<ArrayList<String>> buckets = new ArrayList<ArrayList<String>>();for (int i = 0; i < 26; i++) //make 26 bucketsbuckets.add(new ArrayList<String>());

// repeat sort on different characters, from right to leftfor (int charPos = 9; charPos > -1; charPos--) {for (String word : data) { // for each input wordchar c = word.charAt(charPos); // get charint bucketNumber = c - 'A'; // A = bucket 0, B = bucket 1 etcbuckets.get(bucketNumber).add(word); // add to that bucket}

int counter = 0;// go through each bucketfor (int index = 0; index < 26; index++) {for (String s : buckets.get(index)) { // for each worddata[counter] = s; // put back into the arraycounter++;}

buckets.get(index).clear(); // and empty the bucket, for next pos

}}

return data;}

What about

How To Program © Walter Milner 2013                            Page 99 

Page 100: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

ArrayList<ArrayList<String>> buckets = new ArrayList<ArrayList<String>>();

We want to have 26 things, which we are calling buckets. The As go into the first, the Bs go in the second and so on. How many will there be in each bucket? We don't know, so each bucket must be an ArrayList of Strings. We could try and have an array of lists, but you cannot instantiate an array of generic type (because of the way Java does generics). So we have an ArrayList of ArrayLists. The line is

ArrayList< something> buckets = new ArrayList< something >();

where 'something' is an ArrayList<String>.

We can test this by

String[] data =makeRandomWords();print(data);data=radixSort(data);System.out.println();print(data);

This outputs

SDQGTUBYXF

UFPVFSYMYR

XYDYEYBHLE

DSSZBWJSHY

LMFXNSKJOH

RWSHCILAGA

PACJGFVLOP

AGUDGLNHBB

UOMPWYQSJS

XGDIMUKIIH

AGUDGLNHBB

DSSZBWJSHY

LMFXNSKJOH

PACJGFVLOP

RWSHCILAGA

SDQGTUBYXF

UFPVFSYMYR

UOMPWYQSJS

XGDIMUKIIH

XYDYEYBHLE

Exercise

Modify this so that instead of sorting a list of strings of letters like XYDYEYBHLE its sorts lists of 10 digit numbers like 0123853479

How To Program © Walter Milner 2013                            Page 100 

Page 101: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

How fast is radix sort? One pass of n items requires n steps.How many passes? However many characters there are in the key (10 in our example. Is the time is O(kn) where k is the length of the key. That means it is quicker then quicksort.

How To Program © Walter Milner 2013                            Page 101 

Page 102: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Sets

A set is an abstract data type which models (more or less) the mathematical idea of a set ­ a collection of items in no order, and with no duplicates. If you do not know about basic maths sets, it will make more sense if you read about them.

The modelling is limited, because there is usually no Universal Set (sometimes called a Universe of Discourse). Also mathematical sets are immutable, but a set data structure would usually have methods to add and remove items.

The usual operations are

1. contains ­ is a given item an element of a set

2. union ­ return the union of a set with another

3. intersection ­ return the intersection of a set with another

Variadic arguments

The Collections  framework has a built­in data structure of a set, but we will create our own. It will contain the elements in a linked list, but we have to check there are no duplicates. We will have a generic list, built from generic nodes with just a data value and a pointer to the next, as used earlier.  It starts:

package dataStructures;

public class GenSet<T> {GenNode<T> head; // One data member, a pointer to the head

public GenSet() {head = null;}

..

public boolean contains(T val) {GenNode<T> nodePtr = head;while (nodePtr != null) {if (nodePtr.data == val)return true;

nodePtr = nodePtr.next;}

return false;}

   Now we have a constructor with a new feature – variadic arguments:

How To Program © Walter Milner 2013                            Page 102 

Page 103: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public GenSet(T... values) {head = null;for (T value : values) {put(value);}

}

public void put(T value) {if (!contains(value)) {GenNode<T> newNode = new GenNode<T>(value);newNode.next = head;head = newNode;}

}

The triple dots … in the constructor header mean we can have a variable number of arguments, of type T. In the code,this appears like an array, so we just iterate through it, andadd each element to the list. The put() method checks that they are not already in it, to avoid duplicates. Then we can construct a set like:

GenSet<Integer> set1 = new GenSet<Integer>(1, 2, 3, 4, 5);

For union, we make a new set, and iterate through all our elements and add them. Then we iterate through the other set and add them. The put method will ignore duplicates:

public GenSet<T> union(GenSet<T> other) {GenSet<T> newSet = new GenSet<T>();for (GenNode<T> node = head; node != null; node = node.next) {newSet.put(node.data);}

for (GenNode<T> node = other.head; node != null; node = node.next){newSet.put(node.data);}

return newSet;}

For intersection, we go through all elements, and check they are also in the other set, in which case we add them:

public GenSet<T> intersection(GenSet<T> other) {GenSet<T> newSet = new GenSet<T>();for (GenNode<T> node = head; node != null; node = node.next) {if (other.contains(node.data))newSet.put(node.data);

}return newSet;}

We could use this like:GenSet<Integer> set1 = new GenSet<Integer>(1, 2, 3, 4, 5);GenSet<Integer> set2 = new GenSet<Integer>(3, 4, 5, 6);GenSet<Integer> set3 = set1.union(set2);set3.print(); // 6 1 2 3 4 5GenSet<Integer> set4 = set1.intersection(set2);set4.print(); // 3 4 5

How To Program © Walter Milner 2013                            Page 103 

Page 104: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Exercise

1. We have not given the code of the print method. Write it.

2. Write a difference method. The difference of two sets A ­ B are the elements in A with the elements in B removed.

How To Program © Walter Milner 2013                            Page 104 

Page 105: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

IteratorsWe have seen that iteration is a basic algorithmic tool, and simply means repeating something.

In the context of data structures, we are often concerned with a particular type of iteration, namely accessing the elements of the structure, and moving on to the next. The idea is to have an iterator object, which does these two things – accessing an element, and moving on to the next.

Using an index

The non­OO way to do this is to use an index, like

int[] data = {3,4,5,6,7};for (int index=0; index<data.length; index++){.. do something with data[index]..}

but this does not work with data structures without an index, such as a linked list.

Making an iterator

Suppose we want to create and use an iterator on our linked list class which holds integers. We would like to be able to say:

LinkedList list = new LinkedList();list.put(3);list.put(4);list.put(5);ListIterator iter = list.makeIterator();while (iter.hasNext())System.out.println(iter.next());}

That means we need to define a ListIterator class:

package dataStructures;

public class ListIterator {Node where;ListIterator(Node n){where=n;}public boolean hasNext() {return where!=null;}public int next() {int val=where.data;where=where.next;return val;}}

and we need to add a method to LinkedList to get an iterator:

How To Program © Walter Milner 2013                            Page 105 

Page 106: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public ListIterator makeIterator(){return new ListIterator(head);}

So our iterator has two methods – get the next element, andtest whether there is a next element.

In our code, next returns the value at node 'where', and then moves on. That means that at any time, 'where' actually points to the next node.

Interfaces

A Java class is a type of thing.

An interface is a set of abilities ( or a set of capabilities, or a set of processes, or some things something can do).

We define an interface by giving a set of methods, without bodies – no definitions of the methods, no saying how they are done..

For example, cars, bicycles, helicopters, trains, are all typesof things. They would all be classes.

Something they all have in common is moving. Being able tomove is a capability, so this is an interface:

public interface Mover {public void start();public void stop();}

When we define a vehicle, we can indicate it can move by declaring it as implementing the Mover interface. When we do that, we must also actually define the methods in the interface (or the compiler will flag an error):

public class Car implements Mover {double speed;public void start() {speed=30;}public void stop() {speed=0;}}

and

public class Bicycle implements Mover{double speed;public void start() {speed=8;}public void stop() {speed=0;}}

What have we gained by setting up the Mover interface?

How To Program © Walter Milner 2013                            Page 106 

Page 107: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In OOP we try to create computer models. That might be thephysical realities of buildings and streets and cars and so on,  or financial situations, or computer situations like files and windows and buttons and users with passwords, or imaginary worlds in games, and so on.

A class models a type of thing. But another (slightly more subtle) aspect is to model abilities. Our Mover interface doesthat. It says anything that moves must be able to start and stop. It does not say how, since they are no method definitions (they are not allowed). But it defines the Mover abilities. The Mover interface might be implemented by Carsand Bicycles and Trains, but also People and Rabbits and RoadRunners.

We could just  have defined start and stop methods for Car and Bicycle with no Mover interface. But defining and implementing the interface adds another aspect to our modelling ability and makes it more formal.

It also helps because if we say a class implements an interface, the compiler checks that it actually does define those methods, and tells us if it does not.

We cannot instantiate an interface – because the methods have no definitions. But we can have code that looks as if we do. We can say

Mover mover =.....

which makes it look like mover is an instance of Mover. In fact it means that mover is an instance of a class which implements Mover – not the same thing. In turn the compiler then knows that mover will be able to execute the Mover methods.

   

 

The Iterator interface

There is (in java.util) an Iterator interface, with methods next(), hasNext() and remove(). We can implement this interface so as to make a data structure create its own iterator. For example, to modify the generic linked list class defined earlier, we can say:

 

How To Program © Walter Milner 2013                            Page 107 

Page 108: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class GenLinkedList <T> implements Iterator<T> {GenNode<T> head;

..previous methods..

GenNode<T> where;

public Iterator<T> iterator(){where=head;return this;}

@Overridepublic boolean hasNext() {return where!=null;}

@Overridepublic T next() {T val=where.data;where=where.next;return val;}

@Overridepublic void remove() {throw new UnsupportedOperationException();}}

 and we can then use this as:

GenLinkedList<String> s=new GenLinkedList<String>();s.put("one");s.put("two");s.put("three");Iterator<String> iter=s.iterator();while (iter.hasNext())System.out.println(iter.next());

Remember we cannot instantiate an interface. In

Iterator<String> iter=...

it looks like iter is an Iterator object. Its not. It is an instance of  a class which implements the Iterator interface. The iterator method of GenLinkedList says:

public Iterator<T> iterator(){where=head;return this;}

So it returns this, a reference to the executing object, and that is class  GenLinkedList, which implements Iterator<T>. The compiler has checked this ­ otherwise it would have flagged a syntax error.

Exercise

Code the remove() method. You will need another node pointer, to the one before the one pointed to by 'where'.

How To Program © Walter Milner 2013                            Page 108 

Page 109: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The Iterable interface

This has just one method – to create an Iterator. Our generic linked list already has that:

public Iterator<T> iterator(){..}

so we can already say:

public class GenLinkedList <T> implements Iterator<T>, Iterable<T>{...

but what's the point? Because if a class is Iterable, we can use the enhanced for loop on it:

GenLinkedList<String> s=new GenLinkedList<String>();s.put("one");s.put("two");s.put("three");for (String w:s) System.out.println(w);

This is just syntactic sugar. That is, a syntax feature which does not yield any extra functionality beyond what we couldalready do, but it makes the code look a lot cleaner and clearer.

But this is another example of how interfaces can make code more robust. The enhanced for only works on classes which implement Iterable, and this mechanism enables the compiler to check whether it will work

How To Program © Walter Milner 2013                            Page 109 

Page 110: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Trees

I THINK that I shall never see

A poem lovely as a tree.

Joyce Kilmer

A tree is a data structure like this:

That's it. More or less...

Terminology

The root node is 'at the top'.

A node has 0 or more descendant nodes or child nodes

A node which is not the root is a branch node if it has 1 or more descendants

A node with 0 descendants is a terminal node or a leaf node.

The set of nodes descending from a descendant of the root is itself a tree ­ a subtree.

How To Program © Walter Milner 2013                            Page 110 

Page 111: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The depth of a tree is the number of nodes from the root to the lowest leaf.

In a binary tree, nodes have 0 1 or 2 nodes. 

In a balanced tree , the number of nodes in all subtrees are equal.

Ordered Trees

A tree may be ordered in several ways (or not at all). The following shows the successive states of a tree as 5, 3, 8, 6 and 10 are inserted into it:

This tree is left­right ordered. This is often called a binary search tree. Everything to the left of a node is less than thedata at the node, and everything on the right is greater. A sketch of an algorithm to insert a new node to produce this ordering is:

A. Create a new node with the data

B. If the tree is empty, set the root to be this new node, and finish.

C. Start at the root

D. If data at the node is greater than that to be inserted, go left, else go right. Remember which way.

How To Program © Walter Milner 2013                            Page 111 

Page 112: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

E. Repeat the last step until reaching the end (a null pointer).

F. Link the new node as a leaf node there (on the left or right, depending on which way we tried to go)

Exercise

On paper, draw what tree you get if you insert the following into an empty tree : 10, 5, 15, 3, 12, 8, 1, 20 using this algorithm.

Enums

In the insert algorithm, we have to remember if we go left orright. We could do this using an int flag, say using 1 as a code for left and 2 as a code for right:

int way;way=1; // if we went left orway=2; // meaning right

There are two problems with this. First, it involves magic number programming. We would have code like

if (way==1)...

and a maintenance programmer reading the code might be confused as to what 1 signified. The second problem is if there were some bug, we might have way becoming 3. That is a valid value for an int, so no problem would be shown, but does not make sense – it must be a bug. We want a better way which is more meaningful, and with only allowedvalues possible.

An enum, a special type of class, solves the problem:

enum Dir{LEFT, RIGHT}

Then we can declare a variable of this type (since it is a class) and assign values by symbolic name:

Dir way=Dir.LEFT;

then we get a syntax error if we try to assign an invalid value:

How To Program © Walter Milner 2013                            Page 112 

Page 113: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

A generic Tree

A Java implementation might start as follows. We need a simple node:

class TreeNode<T> {T data;TreeNode<T> left;TreeNode<T> right;

TreeNode(T value) {data = value;left = null;right = null;}}

Then the Tree class starts:

package dataStructures;

public class Tree<T extends Comparable<T>> {TreeNode<T> root = null;enum Dir{LEFT, RIGHT}

What's the Comparable<T>?'

The Comparable interface

When we insert a value into the tree, we need to see if it more or less than that at a node:

if (where.data > val) {

but the data may not be a number, and we cannot compare them using >.

For example, we might be inserting Employee records into atree. What does it mean for one employee to be 'more than' another? Older? Higher salary? Alphabetical order of surname?  Order of payroll number?

How To Program © Walter Milner 2013                            Page 113 

Page 114: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

This is fixed by the Comparable interface. It only has one method – compareTo(). This should be coded to return a negative number if the instance is 'less than' another, a positive value if more than, and zero if equal. We write the code to reflect how we want instances of the class to be ordered. String implements Comparable, for example, and puts string objects in alphabetical order.

So in our tree insertion method, we compare values by

if (where.data.compareTo(val) > 0) {

We can only make the tree out of instances of a class which implements Comparable, which is why we have:

public class Tree<T extends Comparable<T>> {

The tree insertion could be :

public void insert(T val) {TreeNode<T> newNode = new TreeNode<T>(val);Dir way=Dir.LEFT;if (root == null) { // insertion in empty treeroot = newNode;return;}

TreeNode<T> where = root; // start at the rootboolean found = false;while (!found)if (where.data.compareTo(val) > 0) {way=Dir.LEFT;// we should go leftif (where.left == null)found = true; // we've reached the bottom

else // go leftwhere = where.left;

} else {way=Dir.RIGHT; // obviousif (where.right == null)found = true;

elsewhere = where.right;

}if (way == Dir.LEFT) // link new node on the leftwhere.left = newNode;

else // or rightwhere.right = newNode;

}

Tree traversals

Traversing a linked list is obvious ­ we start at the head andgo through each next node until we reach the end. How to traverse a tree?

How To Program © Walter Milner 2013                            Page 114 

Page 115: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Trees are intrinsically recursive. We have a root node, then on the left and right, 2 things which are also trees. This suggests a recursive traversal (where we just output each node we come to)

public void visit(TreeNode<T> where){if (where.left!=null)visit(where.left);

System.out.println(where.data);if (where.right!=null)visit(where.right);

}

To traverse the whole tree, we start by visiting the root. 

This is called an in­order traversal:

a. if there is a left subtree, visit it

b. deal with the data at this node

c. if there is a right subtree, visit it

The nodes in this tree are labelled with the order they wouldbe dealt with in:

We need to visit the root, so we need to make the root readable from outside the package, but we do not want to make it public. Instead we supply a getter method:

public TreeNode<T> getRoot(){return root;}

We could use this like

How To Program © Walter Milner 2013                            Page 115 

Page 116: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Tree<String> words=new Tree<String>();words.insert("One");words.insert("Two");words.insert("Three");words.insert("Four");words.insert("Five");words.visit(words.getRoot());

which outputs:

Five

Four

One

Three

Two

Is this correct?

Tree sort

This means we have a new sorting method. Insert the data into a left­right ordered tree, and then do an in­order traversal on it.

Is this a good method? What is it's time complexity?

When a node is inserted, we start at the root, and work our way down to the insertion point. The time is determined by the number of comparisons, which is the depth of a tree. Sohow deep is a complete tree with n elements?

depth tree Number ofnodes n

1 • 1

2   •

•   •

3

3     •

  •  •

• • • •

7

4         •

    •      •

  •  •    •  •

• • • • • • • •

15

Each time we add another row, we add double the numbers in the row above.

So these number are 1, 1+2, 1 + 2 + 4, 1+2+4+8.. 1+... 2d­1

This is the sum of a geometric progression (Google if you arenot familiar with the term) with first term 1, common ratio 2and d terms, and this is

(1­2d)/(1­2) = 2d­1

so n = 2d­1

How To Program © Walter Milner 2013                            Page 116 

Page 117: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

For large n and d, n   2≈ d

Take logs to base 2 of  both sides, and we have d = log(n)

To insert 1 node, we need log(n) comparisons. So to insert nnodes is O( n log (n) )

The traversal is also O( n log n ) ­ so this is the time complexity of a treesort.

To check this out, inserting varying numbers of random 

integers into a tree and counting the number of steps gives the following. Note that n log n is close to a straight line

Exercise

Modify the above code and check this yourself.

Breadth-first traversal

This is an alternative to an in­order traversal.  The idea of this is to go to the root, then each node one down from the root, then each node one down from those, and so on:

This is easy to implement, using a FIFO queue:

enqueue the root

while queue is not empty

dequeue a node

enqueue its descendant nodes

How To Program © Walter Milner 2013                            Page 117 

Page 118: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

and in Java this is:

public void breadthFirst() {// q is a queue of TreeNodes.GenQueue<TreeNode<T>> q = new GenQueue<TreeNode<T>>();q.enQueue(root);while (!q.isEmpty()) {TreeNode<T> val = q.deQue();System.out.println(val.data);if (val.left != null)q.enQueue(val.left);

if (val.right != null)q.enQueue(val.right);

}}}

used by

Tree<String> words=new Tree<String>();words.insert("D");words.insert("B");words.insert("A");words.insert("C");words.insert("Q");words.insert("M");words.insert("N");words.breadthFirst();

Exercise

1. For the last example, draw that tree on paper. What would the breadth­first traversal sequence be? Check what the code produces. 

2. This traverses each level left to right. Change it so it goes right to left. 

Depth-first traversal

Suppose we use a stack rather than a queue? And push theright node before the left?

public void depthFirst() {GenStack<TreeNode<T>> stack = new GenStack<TreeNode<T>>();stack.push(root);while (!stack.isEmpty()) {TreeNode<T> val = stack.pop();System.out.println(val.data);if (val.right != null)stack.push(val.right);

if (val.left != null)stack.push(val.left);

}}

For example:

Tree<String> words=new Tree<String>();words.insert("4");words.insert("2");words.insert("6");words.insert("1");words.insert("3");words.insert("5");words.insert("7");

words.depthFirst();

outputs

4

2

How To Program © Walter Milner 2013                            Page 118 

Page 119: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

1

3

6

5

7

Exercise

1. Is that correct?

2. Copy this tree and label the nodes with the sequence they would be visited on a depth­first search:

Pretty printing a tree

This means to output a tree in a way which displays and reflects its structure, as in the diagrams we have been drawing.

This is not easy. The output will be done in one of two possible ways. We can use Java 'print', or in another language some character­output equivalent. Or in a graphical environment, there is usually a function to print text  at an x,y position.

In the first case, we can only print text across and down. We must print the root node first. But how far 'across' the root should be will depend on the width of its left sub­tree.

In the second case, the print position can move up and down in any sequence. We still have the problem that the horizontal position of any node will depend on the width of the left sub­tree beneath it.

You might to try to solve this yourself first.

There are different ways to do this. Here is one way:

1. We include in a node a field for its depth ­ so the root node has depth zero. The depth value is calculated when the node is inserted (and must be re­calculated if the tree isaltered)

How To Program © Walter Milner 2013                            Page 119 

Page 120: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

2. We do a breadth first traversal of the tree, and create an auxiliary data structure. This consists of a list of lists. Eachlist contains the nodes at the same depth ­ a row across thetree. See the diagram. Whenever we find a node with a different depth, we start a new list.

3. Unless the tree is complete, there will be 'gaps' beneath where a node has a null left or right pointer. To handle this,we have a 'dummy' node which replaces a gap. Process (2) continues until we have a list containing nothing except dummy nodes.

  

The nth. element of the list of lists will have 2n elements ­ like the first has 20 = 1 element, the root node. This is easilyprinted, just ensuring the width of each item is correct. Try to code this.

Balanced trees

Here are two trees, which differ only in the order in which the nodes are inserted:

The first tree is balanced. Such a tree with n nodes has depth log n, which is the average search time. The second tree is completely unbalanced. Such a tree has depth and search time n ­ a disaster.

There is therefore a big advantage in ensuring our trees are pretty balanced. The two most common ways of doing that are AVL trees and red­black trees. But we will leave those foranother day.

How To Program © Walter Milner 2013                            Page 120 

Page 121: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Maps

A map is an abstract data type with just two operations:

put(key, value) : store a key, value pair in it

get(key): fetch the value associated with given key

The data we are dealing with consists of pairs of data. The first item in the pair is a key and the second item is a 

value. This corresponds to a database table, with rows containing a key, and the value being the other fields. Keys must uniquely identify the pair. Two different pairs with thesame key are impossible. A key is chosen as something unique – a car license plate, a social security number, a passport number, a payroll ID and so on.

We put key­value pairs into the map. We use the key to retrieve it later.

Maps are sometimes called associative arrays. Normal arrays are accessed through a index. Associative arrays are accessed through a key, and you get back the value associated with that key.

Hash tables

A common way to implement a map is as a hash table. A hash table is a data structure designed to make it easy to find an item.

The idea is ­

1. When we insert an item, we calculate somehow where to place it. The calculation is based on the value of the key field.

2. To find an item, given its key, we simply repeat the calculation, and it will tell us where it is.

The calculation is called is called the hash function.

We can see the issues if we start to implement this in Java. For simplicity we will code a hash table where the keys are Integers and the values are Strings. Using generics we coulddeal with any types. We start by defining a data Pair:

How To Program © Walter Milner 2013                            Page 121 

Page 122: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

class Pair{Integer key;String value;

Pair(){key=null;value=null;}Pair(int k, String v){key=k;value=v;}}

Here is a first version of our HashTable class:

package dataStructures;

public class HashTable {private static final int SIZE=100;private Pair[] data=new Pair[SIZE];

public HashTable(){for (int i=0; i<SIZE; i++){data[i]=new Pair();}

}

static int hash(int key){return (key*3)%SIZE;}

public void put(int key, String value){int location = hash(key);data[location]=new Pair(key, value);}

}

So our data  will be stored in an array, with 100 elements, When we put key value pairs into the table, we use the hash function to calculate, from the key, a place to put it. And we put it there.

 

So that we can see what is happening, we'll have this to look at the start of the data

public void peek()

How To Program © Walter Milner 2013                            Page 122 

Page 123: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

{for (int i=0; i<15; i++)System.out.println(i+" : "+data[i].key+" : "+data[i].value);

}

Let's try it out:

HashTable t = new HashTable();t.put(1,"First");t.put(2,"Second");t.put(3,"Third");t.peek();

which outputs:

0 : null : null

1 : null : null

2 : null : null

3 : 1 : First

4 : null : null

5 : null : null

6 : 2 : Second

7 : null : null

8 : null : null

9 : 3 : Third

10 : null : null

11 : null : null

12 : null : null

13 : null : null

14 : null : null

So key 1 goes in at 3. 2 goes at 6, and 3 goes at 9. In the hash function we have (key*3)%SIZE. That % is modulo, so that means we will always be in the range 0 to SIZE­1, and it will fit in the array. For example for key 70 , key *3 is 210, and 210%100 is 10.

We can retrieve a value with a given key by:

public String get(int key) {int location = hash(key);return data[location].value;}

For example:

HashTable t = new HashTable();t.put(1,"First");t.put(2,"Second");t.put(3,"Third");System.out.println(t.get(2)); // Second

Collisions

A structure like this would be very fast, both for insertion and retrieval. Unfortunately there are a few issues.

Key  1 hashes to 3

Key  101 hashes to 303 % 100, which is also 3

Key  201 hashes to 603 % 100, which is also 3.

How To Program © Walter Milner 2013                            Page 123 

Page 124: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Many keys  hash to the same location. This is called a collision. It is inevitable, with only a limited number of  storage locations available, and the key being any integer value. 

If we chose a different hash function, and used more storage, we would get fewer collisions. But unless we have infinite storage, we will always get some collions. How to deal with them?

There are many different techniques. One is simply put the data in the next available location. 

public void put(int key, String value){int location = hash(key);while (data[location].key!=null)location++;

data[location]=new Pair(key, value);}

See what happens:

HashTable t = new HashTable();t.put(1,"A");t.put(2,"B");t.put(101,"C");t.put(201,"D");t.put(301,"E");t.peek();

0 : null : null

1 : null : null

2 : null : null

3 : 1 : A

4 : 101 : C

5 : 201 : D

6 : 2 : B

7 : 301 : E

8 : null : null

9 : null : null

10 : null : null

11 : null : null

12 : null : null

13 : null : null

14 : null : null

Key 1 went in at 3 and 2 at 6. For 101, it hashed to 3, but that was not empty, so it went in at 4, and 201 went in at 5.Similarly 201 hashed to 3, but it was not until 7 that it found an empty slot.

This means we need to change get slightly, since the data may not be at the hash location:

public String get(int key) {

How To Program © Walter Milner 2013                            Page 124 

Page 125: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

int location = hash(key);while (data[location].key != null) {if (data[location].key == key)return data[location].value;

location++;}

return null;}

So we calculate the hash location, then start a linear searchfrom that location, until we find it, or we reach an empty location, in which case it is not present, and we return null:

HashTable t = new HashTable();t.put(1,"A");t.put(2,"B");t.put(101,"C");t.put(201,"D");t.put(301,"E");System.out.println(t.get(301)); // ESystem.out.println(t.get(3)); // null

Collisions mean insertions and retrievals will involve a calculation, and then a linear search. The longer the search,the slower the process.

Exercise

1. Try this out.

2. Insert from 10 to 90 random data values.

3. For each, measure the average retrieval search length

When the data gets to be somewhere near to being full (a large 'load factor'), there will be a lot of long and slow searches. One algorithm to deal with this is that when this happens a new larger storage area is obtained, a new hashing function is used, and existed data is copied into new storage.

For example if the data storage size is n, when the load factor exceeds 0.5, double n. The hash function could still be (3 * key )%n 

Exercise

Try this out. SIZE will no longer be final.

Deletions

The obvious way to do this is

1. find the record

2. write a null record in its place at that location.

But suppose we have

How To Program © Walter Milner 2013                            Page 125 

Page 126: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

0 : None

1 : None

2 : None

3 : (1, 'A')

4 : (101, 'C')

5 : (201, 'D')

6 : (2, 'B')

7 : (301, 'E')

8 : None

9 : None

10 : None

and we delete 201:

0 : None

1 : None

2 : None

3 : (1, 'A')

4 : (101, 'C')

5 : None

6 : (2, 'B')

7 : (301, 'E')

8 : None

9 : None

10 : None

Then we look for 301. This will start at 3, do a linear search, find the None at 5, and decide 301 was not in there.How to fix this?One way would be to have a dummy value of 'Deleted'. When we delete a record, we write Deleted, not None, over it.

Then on a retrieval, we know we must continue searching past a Deleted. But on an insertion, it is OK to write a new record over a Deleted.

Exercise

1. Code this

2. Google hash table, especially hash table wiki. See that hash functions are an active area of research.

The Collections Framework HashMap

In real code you would not normally write your own HashMap, since the Collections framework offers you one already written and tested in java.util:

import java.util.HashMap;

How To Program © Walter Milner 2013                            Page 126 

Page 127: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public class Test {public static void main(String[] args) {HashMap<Integer, String> map = new HashMap<Integer, String>();map.put(1, "One");map.put(2, "Two");map.put(3, "Three");map.remove(1);System.out.println(map.get(2)); // TwoSystem.out.println(map.get(1)); // null}}

We can also iterate through the map:

HashMap<Integer, String> map = new HashMap<Integer, String>();map.put(1, "One");map.put(2, "Two");map.put(3, "Three");for (Integer i: map.keySet())System.out.println(i+" : "+map.get(i));

How does it actually work? You can view the source code online. The code is here. 

This is over 1000 lines with four authors, so is a major piece of work. Where we used a class Pair, the basic element there is Entry, which is an inner class:

687 static class Entry<K,V> implements Map.Entry<K,V> {

688 final K key;

689 V value;

690 Entry<K,V> next;

691 final int hash;

692 …...

The data is held in an array named 'table':

146 /**

147 * The table, resized as necessary. Length MUST Always be a power of two.

148 */

149 transient Entry[] table;

Some parts are very simple:

/**

280 * Returns the number of key-value mappings in this map.

281 *

282 * @return the number of key-value mappings in this map

283 */

284 public int size() {

285 return size;

286 }

287

288 /**

How To Program © Walter Milner 2013                            Page 127 

Page 128: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

291 * @return <tt>true</tt> if this map contains no key-value mappings

292 */

293 public boolean isEmpty() {

294 return size == 0;

295 }

Others not so:

374 /**

375 * Associates the specified value with the specified key in this map.

376 * If the map previously contained a mapping for the key, the old

377 * value is replaced.

378 *

379 * @param key key with which the specified value is to be associated

380 * @param value value to be associated with the specified key

381 * @return the previous value associated with <tt>key</tt>, or

382 * <tt>null</tt> if there was no mapping for <tt>key</tt>.

383 * (A <tt>null</tt> return can also indicate that the map

384 * previously associated <tt>null</tt> with <tt>key</tt>.)

385 */

386 public V put(K key, V value) {

387 if (key == null)

388 return putForNullKey(value);

389 int hash = hash(key.hashCode());

390 int i = indexFor(hash, table.length);

391 for (Entry<K,V> e = table[i]; e != null; e = e.next) {

392 Object k;

393 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

394 V oldValue = e.value;

395 e.value = value;

396 e.recordAccess(this);

397 return oldValue;

398 }

399 }

400

401 modCount++;

402 addEntry(hash, key, value, i);

403 return null;

404 }

which uses the hash function:

257 /**

258 * Applies a supplemental hash function to a given hashCode,

259 * defends against poor quality hash functions. This is critical

260 * because HashMap uses power-of-two length hash tables, that

How To Program © Walter Milner 2013                            Page 128 

Page 129: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

261 * otherwise encounter collisions for hashCodes that do not differ

262 * in lower bits. Note: Null keys always map to hash 0, thus index 0.

263 */

264 static int hash(int h) {

265 // This function ensures that hashCodes that differ only by

266 // constant multiples at each bit position have a bounded

267 // number of collisions (approximately 8 at default load factor).

268 h ^= (h >>> 20) ^ (h >>> 12);

269 return h ^ (h >>> 7) ^ (h >>> 4);

270 }

which relates to hashCode:

hashCode() and .equals()

All classes descend from the class Object, and Object has a method named hashCode. Consequently all classes have a hashCode method, which they may over­ride (or not):

Object obj1 = new Object();

System.out.println(obj1.hashCode()); // gets 1084284121

This relates to the use of hash tables. It also relates to the use of .equals(). How are they related?

Firstly, what are their purposes? The .equals method is intended to tell if two instances are 'equal'. We usually needto code that. For example, suppose we have an employee class, with fields for payrollNumber and name. The payrollNumber identifies the  employee:

class Employee{int payRollNumber;String name;Employee(int id, String n){payRollNumber =id;name=n;}}

but

Employee emp1 = new Employee(27,"John");Employee emp2 = new Employee(27,"John");

System.out.println(emp1.equals(emp2));

gives false – using .equals inherited from Object We need to over­ride it:

public boolean equals(Object other){if (!(other instanceof Employee)) return false;return (payrollNumber==((Employee)other).payrollNumber);}

then two employees are equal if they have the same payroll number.

How To Program © Walter Milner 2013                            Page 129 

Page 130: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Now, hashCode is used in hash tables. But part of the contract of the method is:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. 

This make sense. We use the hashCode to decide where to store an object in the hash table, and where to get it from. So equal objects should give the same hashCode.

But if we over­ride equals, and do not over­ride hashCode, this will not work:

Employee emp1 = new Employee(27,"John");Employee emp2 = new Employee(27,"John");System.out.println(emp1.equals(emp2)); // trueSystem.out.println(emp1.hashCode()); // 1084284121System.out.println(emp2.hashCode()); // 16993205

So how should we over­ride hashCode? Our equals method depends on payrollNumber, and nothing else. So long as our hashcode does the same, it will work:

public int hashCode(){return payrollNumber*31;}

now:

Employee emp1 = new Employee(27,"John");Employee emp2 = new Employee(27,"John");System.out.println(emp1.equals(emp2)); // trueSystem.out.println(emp1.hashCode()); // 837System.out.println(emp2.hashCode()); // 837

This is to ensure we can use Employee in a hashmap. Does it work?

Employee emp1 = new Employee(27,"John");HashMap<Integer, Employee> map = new HashMap<Integer, Employee>();map.put(emp1.payrollNumber, emp1);Employee emp2 = map.get(27);System.out.println(emp1.equals(emp2)); // true

It works – but is it good? How do we choose a good hashing function? If you Google that phrase, you will get many lectures on the question. It needs to be fast to calculate, and it should minimise the number of collisions we get in the hash table – since that will slow access down. We cannot avoid collisions but we can try to minimise them. This depends on the statistical distribution of the key field. For example the English surname 'Smith' is very common, and so a hashing function depending only on surname will produce many collisions and be slow.

But it does not matter much.

The line in HashMap.java:

389 int hash = hash(key.hashCode());

How To Program © Walter Milner 2013                            Page 130 

Page 131: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

shows it does not simply use the hashCode as the hashing function. It uses it and then applies its internal hash to that, with the result that you never get more than 8 collisions.

Memoization

Suppose we have a method which needs to do a lot of computation, and which we need to call often. We can speedthis up if after the result is found, it is stored somewhere in a local cache. Then if the method is called again with the same argument, we look up the result, rather than repeating the calculation. 

In Java we can use a map  as the cache structure. In the following example we have a sine function, and use the Math.sin() to calculate it if we do not already have it. We treat the argument as the angle in degrees.

C can make variables local to functions static, which means they retain their values between function calls. Java has no equivalent, so we make the cache to be a static data member of a class (the keyword static is very confusing, since it has several different meanings in C, and yet another(per class not per object) in Java).

class Funcs{static TreeMap<Integer, Double> sine = new TreeMap<Integer, Double>();public static double sin(int angle){// if we have it already..if (sine.keySet().contains(angle))return sine.get(angle);

// otherwise calculate itdouble rad= angle*Math.PI/180;double result=Math.sin(rad);// cache the resultsine.put(angle,result);// and return itreturn result;}}

which we can use as:

System.out.println(Funcs.sin(0));System.out.println(Funcs.sin(0));System.out.println(Funcs.sin(30));System.out.println(Funcs.sin(30));System.out.println(Funcs.sin(90));System.out.println(Funcs.sin(90));

calling each twice, once calculated and the second looked up.

How To Program © Walter Milner 2013                            Page 131 

Page 132: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Our sine function has limited resolution – we can find sin(5)or sin(6) (degrees), but not sin(5.04). But this implementation would be OK if speed and limited accuracy was required. This would be the case in a video game, where we would need sine for rotations, it would need to be very fast, but 1 degree accuracy would be sufficient.

Memoization gains speed at the cost of increasing memory use, which is a common situation.

Exercise

1. The cache eventually holds entries for degree values 0 to 360 (and may be more). In fact we only need 0 to 90, since the sine of any other angle is equal to a value in this range. For examples – sin(95)=sin(85), sin(365)=sin(5), sin(­5)=sin(5).

Include this in the function so we only cache 0­90

2. This function should become faster with use, as the percentage of cache hits increases. Test whether this is actually the case. 

 

 

How To Program © Walter Milner 2013                            Page 132 

Page 133: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Graphs

This might be a road map, with the letters marking towns, and the numbers might be the travel times between locations.

We might ask ­ is C next to D? Whattowns are next to 

G? What is the fastest route from A to G? Or what quickest journey would visit every town?

But this might also be a computer network, and a router might need to answer such questions about locations on a network.

Or it might be a project management diagram, and we might want to know what is the critical path for the project.

Something like this is a graph. (Different use of the word from a Cartesian x­y graph of a function).     

A graph is an abstract data type, with nodes or vertices, andedges. Here are some terms used with graphs:

simple Only one (or zero) edges between two nodes

directed The edges have arrows. A graph is undirected if they don't

connected Two nodes are connected if there is a path between them. A graph is connectedif there is a path between every pair of nodes. Otherwise the graph is cut into two or more unconnected parts

cycle A set of edges which start and end at the same node 

cyclic graph

Contains at least one cycle. An acyclic graph has no cycles.

In these terms, a tree is a type of graph – a connected acyclic graph.

How To Program © Walter Milner 2013                            Page 133 

Page 134: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Basic graph operations include testing whether two vertices are adjacent, listing all the neighbors of a vertex, and adding and deleting edges.

Representations

There are several ways of representing a graph. One way is an adjacency list. Each vertex has a list of its neighbors, and the adjacency list is a list of these lists.

We will show a slightly different different method. A Graph object contains Edge objects, and an Edge links Node objects. So an OOP model of a graph needs  Node and Edge 

classes. A definition of Graph, using code folding to hide details, is shown here.

How To Program © Walter Milner 2013                            Page 134 

Page 135: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Node is an inner class, so we do not need to worry about a clash with Node in any other namespace:

class Node {String label;Node(String s) {label = s;}

public boolean equals(Object obj) {if (!(obj instanceof Node))return false;

return label.equals(((Node) obj).label);}

}

and our Edge uses Node:

class Edge implements Comparable<Edge> {Node start;Node end;int weight;

Edge(Node s, Node e, int w) {start = s;end = e;weight = w;}

public String toString() {return start.label + "-" + end.label + " ";}

We will need to compare edges, in terms of their weight, so we need to implement Comparable:

@Overridepublic int compareTo(Edge other) {int otherWeight = ((Edge) other).weight;if (weight < otherWeight)return -1;

if (weight > otherWeight)return 1;

return 0;}

}

A Graph starts off:

public class Graph {ArrayList<Node> nodes = new ArrayList<Node>();;ArrayList<Edge> edges = new ArrayList<Edge>();;

public Graph(Node n) {nodes.add(n);}..

so a Graph has a list of vertices, and a list of edges, and we provide a constructor to make a graph from just one node. Here is a simple test graph:

How To Program © Walter Milner 2013                            Page 135 

Page 136: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

We will use the class like:

Graph g = new Graph("AC3AB2BC1CD4BD8BE9ED7");System.out.println(g);

So the constructor takes a string containing triples <label><label><weight>:

public Graph(String s) {int charPos = 0;while (true) {char c = s.charAt(charPos);String s1 = "" + c;Node n1 = new Node(s1);if (!nodes.contains(n1))nodes.add(n1);

charPos++;c = s.charAt(charPos);String s2 = "" + c;Node n2 = new Node(s2);if (!nodes.contains(n2))nodes.add(n2);

charPos++;c = s.charAt(charPos);int w = c - '0';Edge e = new Edge(n1, n2, w);if (!edges.contains(e))edges.add(e);

charPos++;if (charPos == s.length())break;

}}

This is restrictive ie labels only 1 character, and weights only 0 to 9. But it is convenient. toString is

public String toString() {String s="Graph - Nodes ";for (Node n:nodes)s+=n.label+" ";

if (!edges.isEmpty()){s+=" Edges: ";

for (Edge e : edges)s+=e + " ";}

return s;}

so the output for our test graph is:

Graph - Nodes A C B D E Edges: A-C A-B B-C C-D B-D B-E E-D

This representation is potentially inconsistent – the list of edges could involve a node not in the list of nodes. But it does cater for disconnected graphs.

Exercise

1. With this representation, write a method to display a list of all the neighbors of a vertex with a given label,

2. and whether two vertices are adjacent.

How To Program © Walter Milner 2013                            Page 136 

Page 137: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Kruskal's Algorithm

The task is to find a minimal spanning tree (mst). That is, a set of edges which connect all vertices in a tree, and which has minimal total weight.

Exercise

Try to work out the mst for our test graph

The algorithm is simply:

1. Put the edges into increasing order by weight

2. Create a set of graphs, each consisting of a single vertex from  the graphs 

3. Then for each edge in turn, if it links two graphs in the set,combine those graphs.

Suppose we do this for our test graph above. The edges in order of increasing weight are:

BC BA AC CD DE DB BE

Our initial set of graphs, with just single nodes, is 

A B C D E

Then we do step 3. BC obviously links B and C, so our set of graphs becomes

A B­C D E

BA links A with B­C, so we get 

A­B­C D E

AC does not link any of these 3 graphs

CD links A­B­C and D

A­B­C­D E

then DE

A­B­C­D­E

DB and BE do not link anything.

So A­B­C­D­E is our mst.

Coding Kruskal

Kruskal produces a mst, which is a graph, so the outline is

How To Program © Walter Milner 2013                            Page 137 

Page 138: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public Graph kruskal() {..return .. the mst graph;}

For step one, the Collections  class offers a static method to sort a collection, so long as it implements Comparable:

Collections.sort(edges);

For step two, we need a collection of Graphs, with just one node:

ArrayList<Graph> graphs = new ArrayList<Graph>();for (Node n : nodes)graphs.add(new Graph(n));

For step three, we must iterate through the sorted edges. For each edge, we must check if it links any pair of graphs –which means a nested loop to check each pair. If we find a pair it does link, we join them, and go on to the next edge.

When we join two graphs g1 and g2, we merge g2 into g1, and we need to remove g2 from the set. However removing an item from a collection as you iterate through it produces an Exception. So, we copy the set, remove the g2 from the copy, then copy the set back:

for (Edge e : edges) {ArrayList<Graph> copy = (ArrayList<Graph>) graphs.clone();for (Graph g1 : graphs) {boolean flag = false;for (Graph g2 : graphs) {if (Graph.links(e, g1, g2)) {System.out.println("Join on "+e+" from "+g1+"to "+g2 );g1.join(g2, e);copy.remove(g2);flag=true;break;}

}if (flag) break;}

graphs = (ArrayList<Graph>) copy.clone();}

 The println is there mostly for debugging. The .clone method makes a shallow copy. That means it creates a newArrayList, and for each object refernced in 'graphs', it creates a copy reference in the 'copy' list. But it does not create copies of the Graph objects in the list. In this case, that's fine.

After this, 'graphs' should contain just one graph, which is what we return:

return graphs.get(0);}

 

How To Program © Walter Milner 2013                            Page 138 

Page 139: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

A sample run is:

Graph g = new Graph("AC3AB2BC1CD4BD8BE9ED7");Graph k = g.kruskal();System.out.println(k);

which outputs:

Join on B-C from Graph - Nodes B to Graph - Nodes C

Join on A-B from Graph - Nodes A to Graph - Nodes B C Edges: B-C

Join on C-D from Graph - Nodes A B C Edges: B-C A-B to Graph - Nodes D

Join on E-D from Graph - Nodes E to Graph - Nodes A B C D Edges: B-C A-B C-D

Graph - Nodes E A B C D Edges: B-C A-B C-D E-D

How To Program © Walter Milner 2013                            Page 139 

Page 140: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Graphics AlgorithmsThis section is about some algorithms relating graphics (notgraphs).

Background

Code to output to a graphics device is very dependent upon the hardware and system software. Consequently it varies alot across platforms, and so general purpose languages do not have primitives to handle graphics ­ they are not 'built­in' to the language itself. Instead, the usual approach is to use a graphics library to provide this facilities. The library might be device specific, or it might be possible to use the same commands on a range of different devices by using library versions for these different devices.

For Java, there are several graphics libraries available. A commonly used one is Swing. It offers a range of 'widgets' like windows, text input boxes, labels, buttons and so on. We will only show the minimum needed to program some graphics.

Graphics output is usually done in 1 of 2 ways. The most common is as a rectangular array of dots, which are pictureelements or pixels. Each pixel has a colour. The colour is often specified by giving red, green and blue components, each in the range 0 to 255  ­ the values which will fit into 

one byte.  Pixels have x,y co­ordinates, and x is 'across' as usual, but y is often measured down from the top of the screen or a window. So we make a graphics image by colouring the dots.

The second way is by using vector graphics. This uses lines rather than dots. However most output devices ­ lcd, led or plasma ­ physically use pixels, and vector graphics are usually converted to dots. 

A Swing window

The Swing class JFrame models a standard GUI window object, with borders, moveable, resizable and so on. It is common to sub­class a JFrame to customize it to what we want. We will call ours MyWindow:

How To Program © Walter Milner 2013                            Page 140 

Page 141: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

package graphics;

import javax.swing.JFrame;

public class MyWindow extends JFrame {

public MyWindow(){setSize(500,500);setTitle("This is a title");setVisible(true);}

}

Starting a Swing application must be done correctly. This isbecause Swing uses a separate 'event­despatching thread' to handle events like re­sizing a window or clicking a button. To work properly, code to control a Swing application must run in that thread. This does that:

import graphics.MyWindow;

import java.awt.EventQueue;

public class Test {

public static void startGUI(){MyWindow win = new MyWindow();

}

public static void main(String[] args) {EventQueue.invokeLater(new Runnable() { public void run() { startGUI(); } });}}

This produces the following on Ubuntu 12.04 Linux. The exact appearance will depend on the platform. 

How To Program © Walter Milner 2013                            Page 141 

Page 142: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Drawing an image

The Swing class BufferedImage represents an image. It is buffered in the sense that it is held in a rectangular array ofpixels, which can be manipulated, which is why we will use it. 

We modify the constructor:

public class MyWindow extends JFrame {BufferedImage img;

public MyWindow() {setSize(500, 500);setTitle("This is a title");

img = null;ClassLoader classLoader = Thread.currentThread().getContextClassLoader();InputStream input = classLoader.getResourceAsStream("t.jpg");

try { img = ImageIO.read(input) ;} catch (IOException e) {e.printStackTrace();}

setVisible(true);}

This creates the BufferedImage by reading the graphics file named 't.jpg', which should be in the same folder as the MyWindow class file.

We also add a paint method to the MyWindow class:

How To Program © Walter Milner 2013                            Page 142 

Page 143: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;g2.drawImage(img, 0,0, null);}

paint is a call­back method. When the window is initially drawn, or when it needs to be re­drawn after a move or re­size or whatever, the system calls 'paint' to draw it. We do not call 'paint'. In this case, paint justs draws the  image. The result is:

We will now manipulate this image – but to do so we must manipulate the bits in the pixels, for which we need the bitwise operators.

Bitwise operators

Everything in digital systems is represented by patterns of binary digits – 0s or 1s – bits. This includes program code and all data, which means numbers, text, sound, graphics and the rest. An int, for example, is encoded as a sequence of 32 bits. Usually we treat the data as an int, and need not worry about the bits. But sometimes we do need to do things with the bits, and most languages, including Java, have bit­oriented operators to do this.

Full details of number bases and digital data representationin Java is available here.

The bitwise operators take 1 or 2 bit patterns, and produce a new bit pattern as the result. The result is formed by applying the operation to each pair of bits. & is AND, | is OR. For example:

int b1=0B11111010; int b2=0B11111100; int b3 = (b1 & b2); String r=Integer.toBinaryString(b3); System.out.println(r); // 1111 1000

This uses 'binary literals' introduced in Java 7. You might need to update.

Why 1111 1000? We are ANDing pairs of bits:

How To Program © Walter Milner 2013                            Page 143 

Page 144: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

b1 1 1 1 1 1 0 1 0

b2 1 1 1 1 1 1 0 0

b3 1 1 1 1 1 0 0 01 A

ND

 1 =

 1

0 A

ND

 1 =

 0

1 A

ND

 0 =

 0

0 A

ND

 0 =

 0

   Bitwise OR is:

int b1=0B11111010; int b2=0B11111100; int b3 = (b1 | b2); String r=Integer.toBinaryString(b3); System.out.println(r); // 1111 1110

The bitwise NOT is ~

int b1=0B11111111_11111111_11111111_11111010; int b3 = ~b1; String r=Integer.toBinaryString(b3); System.out.println(r); // 101

We need to explain this. The Java 7 binary literal is of type int, and so has 4 bytes = 32 bits. When we say

int b1=0B11111010;

the leading bits are taken to be 0s, so this is actually 0000 0000 1111 1010.

We want the leading bits to be 1's, so we say

int b1=0B11111111_11111111_11111111_11111010;

This also uses the feature of being able to put in _ to track the bit positions. 

When we ~ this, all those 1s turn to 0s. The 3 least significant bits 010 are inverted to 101, which is output. toBinaryString omits leading 0s.

The XOR bitwise operator is ^.

Bit shifts

The bit shift operators produce a new bit pattern by moving the bits in an input pattern left or right a number of places. >> shifts to the right, and << to the left. For example:

int a = b << 4;

means a has the same bits as b, but shifted 4 places to the left.

We can use a bit shift to write a better routine to convert anint to a displayable binary pattern.

A better binary

Integer.toBinaryString suppresses leading 0s, and does not insert spaces every 4 bits. Here is a better version:

How To Program © Walter Milner 2013                            Page 144 

Page 145: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

static String binary(int i) { StringBuilder s = new StringBuilder(); for (int bitPlace = 0; bitPlace < 32; bitPlace++) { int bit = i & 1; i >>= 1; if (bitPlace % 4 == 0) { s.append(" "); } s.append(bit); } s = s.reverse(); return new String(s); }

This forms the result in 's'. A StringBuilder is like a String, but is mutable so a lot more efficient here.

We have a loop going round 32 places, since we know ints have 32 bits.

int bit = i & 1;

This uses the idea of a bit mask (explained more later). We are ANDing each bit in i with 1, which in binary will be 00000..001. If you AND a bit with 0, you get 0. If you AND itwith 1, you get the bit unchanged ( ) AND 1 = 0, 1 AND 1 = 1). So i & 1 makes every bit 0, except for the right­most one,which is unchanged. So i & 1 gets us the rightmost bit.

i >>= 1;

is the same as

i = i >> 1;

so it shifts the bits in i right one place. 

s.append(bit);

puts our bit on the end of s. 

if (bitPlace % 4 == 0) { s.append(" "); }

puts a space in the result every four places to make it more readable.

The append builds up the bits left to right, so we need

s = s.reverse();

Finally

return new String(s);

returns a new String constructed from the StringBuilder s.

For example

int b1 = 0B1010; System.out.println(binary(b1)); // get 0000 0000 0000 0000 0000 0000 0000 1010 int b2 = b1 << 4; System.out.println(binary(b2)); // get 0000 0000 0000 0000 0000 0000 1010 0000

Bit masks

A bit mask is a bit pattern which we AND or OR  with a given pattern, to isolate or change specified bits.

How To Program © Walter Milner 2013                            Page 145 

Page 146: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

If you AND something with a bit mask, you force to zero those bits where you have a 0, and leave the rest unchanged. For example:

int b1 = 0B1010; System.out.println(binary(b1)); // 0000 0000 0000 0000 0000 0000 0000 1010 int b2 = b1 & 0B0011; System.out.println(binary(b2)); // 0000 0000 0000 0000 0000 0000 0000 0010

If you OR something with a bit mask, you force bits to 1 where the mask has a 1:

int b1 = 0B1010; System.out.println(binary(b1)); // 0000 0000 0000 0000 0000 0000 0000 1010 int b2 = b1 | 0B11110000; System.out.println(binary(b2)); // 0000 0000 0000 0000 0000 0000 1111 1010

If you XOR a bit mask, you invert the 1 bits. If you do it twice, you get back to where you started from    

int b1 = 0B1010; System.out.println(binary(b1)); \\ 0000 0000 0000 0000 0000 0000 0000 1010 int b2 = b1 ^ 0B11111111; System.out.println(binary(b2)); \\ 0000 0000 0000 0000 0000 0000 1111 0101 b2 = b2 ^ 0B11111111;

System.out.println(binary(b2)); \\ 0000 0000 0000 0000 0000 0000 0000 1010

Pixel bit manipulation

BufferedImage can handle the colour of the pixel as an int, withthe red green and blue components as 8 bit fields. So yellow, forexample, is coded in the 32 bits of an int as 00 FF FF 00 – the red component is ff = decimal 255, green is ff = 255, and blue iszero. 

So if we AND a pixel with 0x0000ff, we will force red and green components to zero, and be left with just the blue:

public void process() {for (int row = 0; row < img.getHeight(); row++) {for (int col = 0; col < img.getWidth(); col++) {int pixel = img.getRGB(col, row);pixel = pixel & 0x0000ff;img.setRGB(col, row, pixel);}

}}

which is used like:

How To Program © Walter Milner 2013                            Page 146 

Page 147: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

MyWindow win = new MyWindow();win.process();

to produce

Exercise

1. What would 

int pixel = img.getRGB(col, row);pixel &= 0x00ff00;img.setRGB(col, row, pixel);

do in the above loop?

2. Alter this to obtain just the red component.

This code rotates the red green and blue components:

public void process() {for (int row = 0; row < img.getHeight(); row++) {for (int col = 0; col < img.getWidth(); col++) {int pixel = img.getRGB(col, row);int red = (pixel & 0xff0000) >> 16;int green = (pixel & 0x00ff00) >> 8;int blue = pixel & 0x0000ff;pixel = (blue << 16) + (red << 8) + green;img.setRGB(col, row, pixel);}

}}

How To Program © Walter Milner 2013                            Page 147 

Page 148: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Using transparency

An alternative pixel format for a BufferedImage is RGBA. As wellas the red green and blue components, each pixel also has an alpha component for transparency, with 0 being fully transparent and ff fully opaque. The alpha component is in bits 24 to 31.

Our image is RGB because we constructed it from a loaded jpg. We can write that into an RGBA image:

public class MyWindow extends JFrame {BufferedImage img;BufferedImage rgbaImage;

public MyWindow() {setSize(500, 500);.. as before to read img..rgbaImage = new BufferedImage(img.getWidth(null), img.getHeight(null),

BufferedImage.TYPE_INT_ARGB);Graphics2D g2 = rgbaImage.createGraphics();g2.drawImage(img, 0, 0, null);g2.dispose();setVisible(true);}

then in paint we draw rgbaImage not img.

We can then manipulate the alpha:

public void process() {for (int row = 0; row < rgbaImage.getHeight(); row++) {for (int col = 0; col < rgbaImage.getWidth(); col++) {int pixel = rgbaImage.getRGB(col, row);int transparency = (int) (col * 255.0 / rgbaImage.getWidth());pixel = (transparency << 24) + (pixel & 0x00ffffff);rgbaImage.setRGB(col, row, pixel);}

}}

this means the transparency varies from 0 at the left to ff at theright:

How To Program © Walter Milner 2013                            Page 148 

Page 149: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Exercise

Alter this so the image is opaque at the centre and transparent at the edge.

Plotting a pixels

Swing widgets like text fields are not drawn one pixel at a time. But plotting single pixels is the foundation of graphics, so we want to be able to do that. We modify the window class:

package graphics;

import ..

public class MyWindow extends JFrame {BufferedImage img;public MyWindow(){setSize(500,500);setTitle("This is a title");setVisible(true);img = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB );}

public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.drawImage(img, null, null); }

public void plotPixel(int x,int y,int col){img.setRGB(x, y, col);}}

A BufferedImage is a 2D image, usually used to display an image file. We use it because we can set pixels on a BufferedImage. We create one 500X500 pixels in size.

plotPixel justs calls setRGB to plot a pixel on the image.

We can use this like:

How To Program © Walter Milner 2013                            Page 149 

Page 150: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

MyWindow win = new MyWindow();win.plotPixel(50,50,0x00ff00);win.plotPixel(54,50,0xffff00);win.plotPixel(58,50,0xff0000);

which outputs:

The color parameter to plotPixel encodes red green and bluecomponents with the blue as the lower 8 bits, green as the next, and red as the next. It is then easiest to write this in hex. So

0x0000ff is pure blue

0x00ff00 is pure green

0xffff00 is red+green = yellow and so on.

Line drawingalgorithms

Once we can plot asingle pixel ­ how canwe draw a line?

We will look at twoalgorithms to do this,firstly a basic simpleone, then an improvedone.

We want to draw the line from point (x0,y0) to (x1,y1). The slope of that line is 

 (y1­y0)/(x1­x0), 

and the equation of the line through those two points is 

y = y0+ slope * x.

(you need a little co­ordinate geometry to follow this).

We will iterate x values from x0 to x1, in steps of 1, so our xvalues are integer co­ordinates. At each step, the change in y is dy = slope X dx. But dx is 1, so dy=slope, and y changeslike y = y + slope.

How To Program © Walter Milner 2013                            Page 150 

Page 151: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

When we move from one x to the next, the y co­ordinate of the plotted pixel is the same as the last, or maybe one more.(Why cannot it be 2 or more? See below). In the diagram, the first pixel plotted is at (x0,y0), shown in red. The next pixel to the right is at x=x0+1, But should we plot this at the same y0 (the yellow one), or at y0+1 (the green one)? If yis closer to y0+1 than y0, we should plot the green one. 

We decide by working out the error, between the exact y value, and the current pixel y. If this is less than 0.5, the lower pixel is closer ­ otherwise we plot the upper one.

public void line(int x0, int y0, int x1, int y1, int col){double slope=(double)(y1-y0)/(x1-x0);double exacty = y0;int y = y0;for (int x = x0+1;x<x1+1; x++ ){exacty=exacty+slope;double diff=y-exacty;if (diff<0.5)y=y+1;

plotPixel(x,y,col);}

}

We can use this for example

MyWindow win = new MyWindow();

win.line(0,0,100,50, 0xff0000);

which produces this: 

How To Program © Walter Milner 2013                            Page 151 

Page 152: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

(we are measuring y down from the top of the window).

We make two developments from this.

Suppose we say

win.line(0,100,100,50, 0xff0000);

then we get:

This is because y either stays as it is, or we increase it by 1.There is no option for y to decrease, so if y0>y1 it will not work.

We can fix this by checking if y0<y1 or not, and setting a flag showing if we are going up or down. Then in the loop weincrease or decrease y according to the flag.

Exercise

Modify the code according to this plan

Secondly ­ suppose we draw a line from 0,0 to 50,150 ­ in other words, a steep line. In fact we get this ­ a line with slope=1:

We only increase y by 1 each step, so we cannot get a slope more than 1.

How To Program © Walter Milner 2013                            Page 152 

Page 153: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

See the diagram at the left. If we iterate through x, we only have 3 x values, so only 3 pixels. If we iterate through y values, we will get 7 points, and 7 pixels.

So if the line is steeper than 1 (if y1­y0 > x1­x0), it is better to iterate through y, and calculate x,than to iterate on x and calculate 

y.

Exercise

Modify the code again to achieve this.

An integer-arithmetic only line

The problem with this is that y and slope are floating point numbers, so y=y+slope involves floating point arithmetic, and this is relatively slow. It would be much faster if we could only use integer arithmetic ­ and since pixel co­ordinates must be integer, this must be possible. The 

time to draw 1 line is negligible, but in a game with 3D graphics we must draw millions of lines every second, so speed is very important. So we look for an algorithm with only integer arithmetic in the loop.

We can do this if we scale up the variables involved, by a factor of (x1­x0), except for the x and y pixel co­ordinates plotted:

public void line(int x0, int y0, int x1, int y1, int col) {

int scale = x1 - x0;int slope = y1 - y0; // real slope = this slope/scaleint exacty = y0 * scale; // real exacty = y0int limit = scale / 2; // real limit is 0.5int y = y0;for (int x = x0 + 1; x < x1 + 1; x++) {exacty = exacty + slope; // real exacty = this / slopeint diff = y * scale - exacty;if (diff < limit)y = y + 1;

plotPixel(x, y, col);}

}

The version with floating­point arithmetic is sometimes called DDA, and the integer­arithmetic version is Bresenham's algorithm. But on the web you will find integerDDA, and floating­point Bresenham.

How To Program © Walter Milner 2013                            Page 153 

Page 154: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

In practice, this is usually done not in the core processor, but in a graphics processor. It will usually use Bresenham'sinteger algorithm, but implemented in hardware rather thansoftware, so that it is extremely fast and will do this in 3D millions of times per second.

Anti-aliasing

Drawing a line as a set of pixel dots works perfectly for vertical and horizontal lines. But lines at any other angle produce the jaggies. For example

win.line(0,50,300,55, 0xffff00);

is almost horizontal, and produces when magnified:

Anti­aliasing tries to reduce the  problem of the jaggies. There are many approaches.   We will show an approach where instead of plotting one pixel at one x co­ordinate, we plot 3 – one above and one beneath the one closest to the exact y position. And we weight the three pixels with a 

colour intensity reflecting how far they are from the exact position. We mulitply them by a scale factor which is smaller if they are further away. But to do that we need to use some bit operations.

Let's see what happens if we scale yellow by a factor  of 0.12decimal. ffff00 in hex = decimal 16 776 960. If we mulitply by .12 we get 2 013 252.2, and if we turn this back to hex we get 1e b8 33

But suppose we multiply the separate components by 0.12. These are 255, 255 and 0. Multiplied by 0.12 gives 30.6 30.6 0, which in hex is 1e 1e 00 which is completely different green and blue components.

What we need to do is to separate the red green and blue components, multiply them separately by a scale factor, then put them back together again. How do we do that?

public int scaledColor(int col, double scale) {int blue = col & 0xff; // get lower 8 bits// get bits 8 to 15, shifted to the rightint green = (col & 0xff00) >> 8;// get bits 16 to 23, shifted to the right

int red = (col & 0xff0000) >> 16;// mulitply components by scale factorblue = (int) (blue * scale);green = (int) (green * scale);red = (int) (red * scale);// re-assemblereturn (red << 16) + (green << 8) + blue;}

How To Program © Walter Milner 2013                            Page 154 

Page 155: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

An anti-aliasing algorithm

We draw a line iterating across x, calculating an exact y value each time (named yx). We then find the nearest integer y value ( y ) and plot that pixel, and y­1 and y+1, thepixels above and below that one. We modify the three pixels'color depending on how far away they are from yx.

The diagram shows the 3 pixels, at y, y­1 and y+1, and the exact position yx. Each pixel has size 1. d1 d2 and 3 are thedistances of the centres of the pixels from yx.

We have:

y = (int) yx

d1 = yx+­y+1/2

d2=yx­y­1/2

d3=y+1.5­yx

We scale each pixel inverselyproportional to d1, d2 and d3, scaled so the total weighting is 1. In other words the weights are k/d1, k/d2 and k/d3, where 

1 = k/d1 + k/d2 + y/d3

so

y  = 1 /( 1/d1 + 1/d2 + 1/d3) 

 So our code is as follows:

public void lineAnti(int x0, int y0, int x1, int y1, int col) {double slope = (double) (y1 - y0) / (x1 - x0);double yx = y0;for (int x = x0 + 1; x < x1 + 1; x++) {yx = yx + slope;int y = (int) yx;double d1 = (yx - y + 0.5);double d2 = Math.abs(y + 0.5 - yx);double d3 = (y + 1.5 - yx);double k = 1.0 / (1 / d1 + 1 / d2 + 1 / d3);int c1 = scaledColor(col, k / d1);int c2 = scaledColor(col, k / d2);int c3 = scaledColor(col, k / d3);plotPixel(x, y - 1, c1);plotPixel(x, y, c2);plotPixel(x, y + 1, c3);}

}

If we run this:

MyWindow win = new MyWindow();win.line(0,50,300,55, 0xffff00);win.lineAnti(0,60,300,65, 0xffff00);

we get:

How To Program © Walter Milner 2013                            Page 155 

Page 156: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Floodfill

Most graphics programs have a 'floodfill' tool. You click a point in an image, and it 'pours paint' there, spreading out until it reaches another color. How to do that?

One way is using recursion. In pseudo­code:

floodfill(x,y, targetColor, fillColor):

get pixel colour at x,y

if colour is not targetColour, return

set pixel at x,y fillColour

floodfill(x+1,y, targetColor, fillColor)

floodfill(x­1,y, targetColor, fillColor)

floodfill(x,y+1, targetColor, fillColor)

floodfill(x,y­1, targetColor, fillColor)

so we check the starting pixel, and if it is not target colour, we do nothing, and stop. Otherwise we plot that point, and recurse on the 4 pixels around it, north south east and west.

How to do this in Java? We need an area to fill:

public MyWindow() {.. img = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB); Graphics2D g=img.createGraphics(); g.setColor(Color.red); g.fillRect(50,50,100,100); g.fillRect(75,75,200,300);}

public void paint(Graphics g) {Graphics2D g2 = (Graphics2D) g;g2.drawImage(img, null, null);}

which outputs:

How To Program © Walter Milner 2013                            Page 156 

Page 157: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Then floodfill is:

public void floodfill(int x, int y, int target, int fill){int pixelColor=img.getRGB(x,y);if (pixelColor!=target) return;img.setRGB(x, y, fill);floodfill(x+1,y, target, fill);floodfill(x-1,y, target, fill);floodfill(x,y+1, target, fill);floodfill(x,y-1, target, fill);}

 which we can use by

MyWindow win = new MyWindow(); win.floodfill(60,60,0xffff0000, 0xff0000ff);

which outputs this, 

and the error message:

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError

For each recursive call, the return address is pushed on thesystem stack ­ and not popped off until the call ends. We have a lot of pixels, so we use a lot of stack space ­ more than the JRE allows. So we get some pixels filled, but not 

How To Program © Walter Milner 2013                            Page 157 

Page 158: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

all. We could try to fix this by allocating more stack space, or we can use our own stack – as an instance of java.util.LinkedList. We first define an inner class in MyWindow:

class Pair {int x;int y;Pair(int a, int b) {x = a;y = b;}

}

and use it like:

public void floodfill(int x, int y, int target, int fill) {LinkedList<Pair> stack = new LinkedList<Pair>();stack.push(new Pair(x, y));while (!stack.isEmpty()) {Pair pair = stack.pop();int pixelColor = img.getRGB(pair.x, pair.y);if (pixelColor == target) {img.setRGB(pair.x, pair.y, fill);stack.push(new Pair(pair.x + 1, pair.y));

stack.push(new Pair(pair.x - 1, pair.y));stack.push(new Pair(pair.x, pair.y + 1));stack.push(new Pair(pair.x, pair.y - 1));}

}}

How To Program © Walter Milner 2013                            Page 158 

Page 159: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

File Structures and algorithms

In all the other sections, we have manipulated data held in RAM. We also need to use files, mostly because RAM is volatile, so the data is lost when the device is switched off – while files are usually held on a non­volatile medium. A second reason is capacity – some applications handle hundreds of millions of data items, too much to hold in RAM at the same type.

Reading and writing text files

Java and related languages (C and C++) treat file use as a part of input and output (I/O). So input from the keyboard is treated as a standard input stream, and character output to the screen is a standard output stream.

Java has a wide set of classes relating to I/O, and since this text is about programming, not Java, we will not go through them all. We will just point out a few basic concepts.

package filing;

import ...

public class TextFile {public static void write(String filename, String... lines) { BufferedWriter writer;try {writer = new BufferedWriter(new FileWriter(filename));for (String s : lines) {for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);writer.write(c);}writer.newLine();}writer.close();

} catch (Exception e) {e.printStackTrace();}}

The key class here is BufferedWriter, and the key method write(). Java writer classes in general write characters to a file,  and this is what write() does. We pass a filename to our method, folowed by variadic set of strings to write to the file. Once the BufferedWriter is constructed, we loop through the strings, and for each one, loop through its characters, writing each one out to the file. After that we write a newline character to the file.

How To Program © Walter Milner 2013                            Page 159 

Page 160: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Opening and writing to the file is in a try..catch.., since several things might go wrong. If the file does not already exist, it will be created – and we might not have rights to create files there, or it might be a read­only device, and so on.When we are writing to the file we might get a hardware error.In this simple example we just print the stack trace of the exception. In a real application we should do something more constructive.

We can call this method for example as:

TextFile.write("data.txt","ABC", "01", "012");

We could check the contents of the file by looking at it directlywith a hex editor, which displays the bytes in a file – such asmidnight commander = mc on Linux:

This shows there are 10 bytes (=hex a) bytes in the file. The first three are hex 41 42 43, which is decimal 65, 66, 67, the Unicode of A Band C. Then the 0a is a control code – the new line. 30 31 are decimal 48 49, codes for 1 and 2. Note we are not storing 1 as 2 as ints, but as chars.

Using a hex editor is a good way to test if file­writing code is working.

Similarly we can read the text file back in:

How To Program © Walter Milner 2013                            Page 160 

Page 161: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

public static String[] read(String filename) { BufferedReader reader; ArrayList<String> strings = new ArrayList<String>();try {reader = new BufferedReader(new FileReader(filename));String s;while ((s=reader.readLine())!=null) strings.add(s);reader.close();} catch (Exception e) {e.printStackTrace();}String[] result = new String[strings.size()]; strings.toArray(result);return result;}

The method readLine reads a sequence of characters until it reaches a newline, when it stops and returns the characters as a String. When we reach the end of the file, it returns null, and hence the loop. We do not know how many strings we willread in, so we cannot input them into an array. Instead we add them to an ArrayList, and convert that to an array at the end.

Opening and closing files

The OS will use a file handle through which to read and writeto the file. A file handle is a data item which will include the name of the file, the folder path to where it is on the device, which device that is, and so on. The file handle is set up whenthe file is opened. At any one time an OS will have many file 

handles in existence. When we create our BufferedReader in the last section, that included the OS setting up an appropriate file handle. When we have finsihed with the file, we must close it. This will flush any buffers (explained next) and return the file handle to free memory.

If we do not close the file, the handle remains in use – and this is a memory leak. The OS will probably have some limit to the number of file handles which can be open at the same time, and if we keep opening files without closing them, we will eventually reach this limit. So in file use we must always code as a sandwich:

open the file 

use it

close it

Buffers

A buffer is a section of memory used to hold data being transferred. For an output buffer, as here, what happens is asfollows – data is written into the buffer, and when the buffer is full, it is written out to the file.

The write method of BufferedWriter apparently writes a single character into the file. In fact, it only writes it into the buffer in memory, and the buffer is written out when it is full, or when the file is closed.

How To Program © Walter Milner 2013                            Page 161 

Page 162: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Why? Because it takes almost as much time to write one byte out as it does to write a block of say one thousand bytes. So itis much faster to use a buffer and write blocks of data rather than single bytes.

A corresponding process happens on input – even if a single character is apparently read, in fact an entire block is read into an input buffer. Input of further characters than happens(at speed) from that buffer, until it is exhausted and another buffer­full is read.

Binary data files

Binary data files contain bit patterns which correspond to theinternal representation of the data.

Java offers the ObjectOutoutStream as a class which can write objects, and primitives, out to a file, and a corresponding ObjectInputStream to read them. For example:

public static void write(String fileName, int[] data) {FileOutputStream fos;try {fos = new FileOutputStream(fileName);ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeInt(data.length);for (int i : data)oos.writeInt(i);

oos.close();} catch (Exception e) {e.printStackTrace();}}

If we try this out:

int[] data = { 1, 2, 3 };BinaryInts.write("numbers.dat", data);

the file contains:

This is interpreted as

ac ed : a 'magic number' meaning 'this is a Java object  stream file'.

How To Program © Walter Milner 2013                            Page 162 

Page 163: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

00 05 : version number

77 10 : more meta data 

00 00 00 03 : this is the first int we wrote to the file. Ints are 4 bytes using 2's complement format. This is where we wrote the number of ints in the array

00 00 00 01

00 00 00 02

00 00 00 03

The 3 actual ints. These are easy to recognise. A primitive double, and objects, are much harder to see in binary or hex.

So here we store in the file the size of the array, followed by the array contents. That makes it easy to read back:

public static int[] read(String fileName) {FileInputStream fis;int[] result=null;try {fis = new FileInputStream(fileName);ObjectInputStream ois = new ObjectInputStream(fis);int len = ois.readInt();result=new int[len];for (int i=0; i<3; i++){int val = ois.readInt();result[i]=val;}ois.close();

} catch (Exception e) {e.printStackTrace();}return result;}

Serial and random access

The example so far have involvedsimply going through the file, writingdata out from the start, and reading itback in the same way, from thebeginning of the file, in sequence. Thisis serial access. In the early days of

How To Program © Walter Milner 2013                            Page 163 

Page 164: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

computing, file storage was on magnetic tape. On this type of storage, serial access was the only possibility – the only thing which could be done was to read through the file from the start. 

But with hard discs and similar devices, it is possible to movea head directly to any point in the file, without first reading through all preceding data. This is known as random access. This offers 3 basic operations – reading a number of bytes from the current head position  (and advancing the position ofthe head), writing a number of bytes, or seeking – moving the head to a new position at a number of bytes from the start of the file.  

As an example, we can read the last file backwards. The file starts with a six byte magic number sequence, then there are 4 ints, each 4 bytes long. So the ints start 6, 10,14 and 18 bytes in from the file start:

public static void showRandAccess(String fileName){try {RandomAccessFile raFile =new RandomAccessFile(fileName,"r");for (int n=3; n>-1; n--){

raFile.seek(6+4*n);int i = raFile.readInt();System.out.println(i);}

} catch (Exception e) {e.printStackTrace();}

}

If we use this like:

int[] data = { 1, 2, 3 };BinaryInts.write("numbers.dat", data);BinaryInts.showRandAccess("numbers.dat");

it outputs 3 2 1 3

A Map in a file

Random access filing is equivalent to memory, which is also random access, and in memory we can use pointers, which enables many data structures. Random access filing enables pointer equivalents in files, so we can implement many data structures and algorithms on file as in memory (with a gain incapacity and a reduction in speed).

As an example, we will show a file with an index, which we will use as a map. The map will contain key­value pairs, with key being an int and the value a double.

How To Program © Walter Milner 2013                            Page 164 

Page 165: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The file will be structured in two sections – an index and a main data section. The index will be a series of pairs – the keyvalue, followed by an int which says where the corresponding value is in the main block (which is just a sequence of doubles). 

Index Main data 

Key Pointer Values

3 1.0

2 2.0

1 3.0

The class definition starts:

public class IndexedMap {String fileName;int size;RandomAccessFile file;int entryCount = 0;

public IndexedMap(String fn, int s) {fileName = fn;size = s;// each index entry is a key and an index into the main block// which is 2 ints or 8 bytes// so index size is 8*s// main block is size doubles = another 8*s bytes// a key value of -1 flags an 'empty' index entrytry {file = new RandomAccessFile(fileName, "rw");file.setLength(16 * size);// initialise indexfor (int i = 0; i < size; i++) {file.seek(i * 8);file.writeInt(-1);}

} catch (Exception e) {e.printStackTrace();}}

If we use this like:

IndexedMap map =new IndexedMap("map",10);map.put(3, 1.0);map.put(2, 2.0);map.put(1, 3.0);

Then the file 'map' contains:

How To Program © Walter Milner 2013                            Page 165 

Page 166: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

The index runs from offset 00 to 4f. The data block starts at offset 50. The first index entry is ..03, with the pointer to 50, where the first data value is. The data is 3F F0 00 00 00 00 00, which is 1.0 as an IEE 754 format double. The second index entry is 02, with the pointer to 58, which is where 2.0 isstored. Third index entry is 01, with the pointer to 60, where 3.0 is stored.

The class also needs a get method, like

double d=map.get(2);System.out.println(d);

Exercise

1. Write and test the get method. What about if the key isnot present in the map?

2. This is just a sketch outline of how this might work. The most obvious problem is that we cannot open an existing map – whenever we construct a map from a file, itinitialises the map to be empty. We need an overloaded constructor, so that we can open an existing map with datain it. But how to tell how much data is in it? In other words, the values of size and entryCount? Solve this problem.

3. Write a delete(keyValue) method. Make sure get still works.

File devices

None of this Java file code makes any reference to what kind of file hardware is being used. It might be magnetic hard disk, flash memory, CD or DVD, or even in RAM. It also might be local, or on another computer over a LAN, orit might be cloud storage and the user does not know whereit is. How can the same code work different devices?

Because layers of software are running here, with specialisation towards devices occuring at the end of the chain. So in the case of Java, we have:

• Source code compiled into bytecode

• which runs on the JVM

How To Program © Walter Milner 2013                            Page 166 

Page 167: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

• The JVM maps file I/O to OS file I/O operations

• which delegates I/O to the appropriate drivers

• which work with the electronics on the device's electrical interface

So differences in device characteristics are handled by device drivers, which are specific to the electronic device. Issues like error detection and correction are dealt with there. Clearly devices have limitations, such as the impossibility of writing to a read-only CD. But these appear at the Java level as an IOException.

This situation is an example of abstraction. We abstract from real devices the simple abilty to read and write data, and delegate to other layers the task of actually doing that, which will vary from one device to another. The next section expands on the idea of abstraction.

 

  

How To Program © Walter Milner 2013                            Page 167 

Page 168: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

How Java works

This section comes last, in order to show that it does not matter. We can use Java to create algorithmic solutions to problems, without knowing how it works. An important aspect of programming is abstraction. We cannot make sense of that unless we know something about what is the opposite of abstraction ­ which is, how computers work.

How Computers work

This is the same – in principle ­ for all 'computers' – desktops, smartphones, laptops, tablets or high performance computing clusters, smartTVs, smart watches or any digital programmable device.

These all have a processor (CPU) and memory, connected 

by a bus to transfer data. How that is organised in terms of chips varies – it might be a single chip or lots. There are also usually peripheral devices like keyboard and screen. A separate graphics processor which does graphics­related computation in hardware is common. Also there may be some file storage devices like hard discs. The capacity of 

memory and file storage are both measured in bytes, but they are different types of things, in that memory is thousands of times faster than memory. Executing programs are in memory.

Memory might be ROM – read only – or RAM. The RAM holds binary data. It is organised as  bytes of storage, each holding 8 bits ­ 1s or 0s, and each byte having a different address. Each address is itself a string of bits. In fact these are all electronic switches, and we interpret open or closed as 1 and 0. We can do just two things with RAM ­ write something into an address (and over­write what is currentlythere), or read something out (and leave it unchanged).

The binary values held in RAM can represent two things ­ data, and program instructions. Both are just binary strings, and you cannot tell which is data and what are instructions by looking at them.

The CPU can do just two things. It can recognise a program instruction (in other words, decode which one it is), and it can execute it.

The CPU contains a set of registers – a small number, maybe 10 or 20. A register is like a memory location, exceptthat there aren't many of them, access to them is faster, and some have special roles in the execution of instructions.

How To Program © Walter Milner 2013                            Page 168 

Page 169: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

One  is the program counter. It holds an address ­ the address in RAM of the next instruction. This is fetched fromRAM to the processor, the instruction is executed, the program counter is moved on to the next instruction, and the cycle repeats. This is the fetch­execute cycle. 

To get maximum speed, the actual process is more sophisticated then this. 32 or 64 bits are fetched, but this might be 1, 2 or 4 instructions at one time. Execution is pipelined. This means the cycle is split into 8 stages, and insome of these, 2 or 3 actions are performed at the same time. 

The program instructions types are add, subtract, multiply, compare, logical 'and' and so on,  branch to a new instruction address, load and store data to and from memory, and move between registers, and so on.

Machine code

A program instruction in machine code is for example:

1011 1100 1100 0000 1111 1101 1011 1110

Writing programs in this manner is pretty much impossible,since the bit strings are meaningless to humans.

Instead assembly language is used. This looks like for example

mov     %r7, $4

which means move 4 into register r7. The $ is there to showwe mean the actual number 4, not the value stored at address 4 in RAM.

Each assembly language instruction corresponds to exactly one machine code instruction. But they make a lot more sense than a string of 1s and 0s.

Using an assembler and linker

When a program is executing, it must be in binary form as shown above. This is always true. For all 'programs'. Always. In Java or C or Visual Basic. An executing program is machine code.

So we need a way of creating programs looking like

1011 1100 1100 0000 1111 1101 1011 1110

without going crazy.

So we do as follows:

1. Use a text editor to write the program in assembly language, like 'mov     %r7, $4'. This is saved in a file, andthis sort of thing is called source code.

How To Program © Walter Milner 2013                            Page 169 

Page 170: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

2. A piece of software called an assembler reads the source code, and converts it to an intermediate form known as object code. This is mostly carrying out the one­to­one translation from assembler to machine code.

3. Another piece of software, called a linker, is used. This links one or more units of object code, together usually with files from a library of code which can be usefully re­used, and puts it into the form of an executable file. The way this is structured will depend on the operating system.

Hello world on Linux

This tutorial shows how to write and run an assembly language program on Linux (Debian) running on a Pentium.To do it on Windows, you need an assembler and linker ( like masm ) and the assembler format and OS calls will be different. Traditionally, a first program outputs the message'Hello world', so this is what our program will do.

The program does two things – output the message, and end. It outputs a message by making a call to the operating system kernel, rather than doing it itself. The OS can do lots of things like this. 

To output the  message, the kernel needs to know four things, and these are passed to it by putting values in someregisters. It needs to know:

1. What to do. In this case, it is to write out a message. The code for this is 4, and must be in the eax register

2. Where the message starts, in memory. This must be in the ecx register

3. How long the message is, in register edx

4. Where to write it to. In this case, std­out, coded by 1, in register ebx

We actually call the kernel with an int instruction, a 'software interrupt'.

Then we end the program by another system call, with a return code in register ebx (0 means OK) and 1 in eax, meaning end this program and return to the OS.

1. Go into a shell terminal. Use a text editor like gedit to write this:

How To Program © Walter Milner 2013                            Page 170 

Page 171: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

.text # this section is program .global _start # entry point

_start: # write string to stdout movl $len,%edx # third argument: message length movl $msg,%ecx # second argument: pointer to message movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel

# and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel

.data # this section is data

msg: .ascii "Hello, world!\n" # the string len = . - msg # length of it

Programs use memory in segments to hold code, and also data. This program has 2 segments. The first is a data segment, starting .data. The second is a text segment, .text, where the program is. _start marks where execution should begin. There are only 8 actual code instructions ­ everythingelse is information for the assembler. The instructions start after _start

msg is a label. When assembled, it will turn into an addressin memory ­ a binary string. A label is a symbolic address ­ something more meaningful for a human than a string of bits. So msg is the address where "Hello world." will be placed, as ASCII code. The \n is a new line control code.

In .­msg, the dot is the current address, and msg is addressof the start of the message. So len is the number of bytes from the end of the message to the start ­ the length of the message.

2. Save this into a file named hello.s

Go back to the shell.

3. Assemble it with the command

as ­o hello.o hellos.s

This invoke the GCC assembler. The ­o option means to generate object code file named hello.o, from source code hello.s

4. Link it by

ld ­s ­o hello hello.o

This is to produce an executable file named hello, from hello.o. The ­s means remove all symbolic information (labels and so on).

5. Load and run the program by

./hello

How To Program © Walter Milner 2013                            Page 171 

Page 172: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

This program will only work on an Intel Pentium processor (or AMD equivalent), since it contains machine code instructions which are specific to that machine, relating to the registers eax, ebx and so on. It will also only work on something running Linux as the OS, since Windows, for example, has a different set of functions available.  

Using ASCII

Everything in a computer is strings of bits. So how do we store 'characters' ­ letters of the alphabet, punctuation marks and so on? This is done using a character set, like ASCII or Unicode. This is a set of characters, each one having a  corresponding binary pattern.

ASCII stores each character as 8 bits, with a total of 256 characters possible.

For example:

Character Binary Decimal equivalent

A 0100 0001 65

B 0100 0010 66

C 0100 0011 67

..

Z 0101 1010 90

The first ASCII characters are not 'printable' ­ instead, they are control characters, menaing they control printing. ASCIIcode 10 means 'line feed', or go on to the next line.

 Here is an Intel Linux program to output the letter A: 

How To Program © Walter Milner 2013                            Page 172 

Page 173: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

.text # this section is program .global _start # entry point

_start: # write our string to stdout movl $2,%edx # third argument: message length movl $msg,%ecx # second: pointer to message movl $1,%ebx # first: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel

# and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel

.data # this section is data

msg: .byte65,10 len = . - msg

This is similar to the first, except we just output 2 characters, and we use the .byte directive. This tells the assembler to place a sequence of bytes in memory at the current location. In this example, we want 65, ASCII code for A, then 10, ASCII control code for a new line.

Exercise

Try out this program. As in the first example, you will need to1. Type it into gedit or another text editor, and save it in a file named for example ascii.s

2. Assemble it by

as ­o ascii.o ascii.s

3. Link it by

ld ­s ­o ascii ascii.o

4. Run it by

./ascii

Exercise

What is ASCII 66, 65, 68?

Write a program to output BAD followed by a new line   

Doing arithmetic

Here is a program to add 2 and 3, and display the result:

How To Program © Walter Milner 2013                            Page 173 

Page 174: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

.text # this section is program .global _start # entry point

_start:

movl $2, %eax # put 2 into eax addl $3, %eax # add 3 into eax addl $48, %eax # convert digit to ASCII movl $msg, %ecx # put address of msg into ecx movb %al, (%ecx) # store byte in al in location ecx # points to

# write our string to stdout movl $2,%edx # third argument: message length movl $msg,%ecx # second argument: pointer to message movl $1,%ebx # first argument: file handle (stdout) movl $4,%eax # system call number (sys_write) int $0x80 # call kernel

# and exit movl $0,%ebx # first argument: exit code movl $1,%eax # system call number (sys_exit) int $0x80 # call kernel

.data # this section is data

msg: .byte65,10 len = . - msg

This puts 2 into register eax, then adds 3, 

To store the result into memory, we have to use 'indirect addressing'. That is we put the  address in ecx, then store itinto the address pointed to be ecx.

We also wantto store just one byte. Most of the instructions end with l, meaning long or 32 bits. We use movb for move byte, and use register al. Thsi is the lowest 8 bits of eax. 

It then outputs the result using the code as in the previous example.

But first we have to add 48. This is because Linux expects to output a sequence of ASCII characters. And the ASCII code of '5' is 53, not 5, since the code of '0' is 48.

Exercise

1. Try this out

2. Change it so it adds 2 and 7

3. The mnemonic to add numbers is addl. The mnemonic tosubtract is subl. Write a program to subtract 2 from 7 and display the result.

4. Why would adding 5 and 5 be more complicated?

High level language programming

Assembler and machine code are low level. That means they refer to processor registers, memory registers and so on. The logic of the problem solution is obscured by references to the actual machine.

How To Program © Walter Milner 2013                            Page 174 

Page 175: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

Another problem with low level code is that it is platform­dependent. The program has to be re­written completely to run on a machine with a different processor, since it will have different registers and different instructions. And it must be re­written for a different OS, like Mac OS X instead of Linux, since the system calls will differ. 

That means that a high level language is usually preferable. In a language such as C, we then have a different step in the chain:

1 Write the source code in C

2 Compile it into object code

3 Link it to produce an executable file

The compiler is an equivalent to the assembler, except that it inputs code in C rather than assembler.

An IDE may well have a single 'Run' button. In fact this saves the source code, compiles it, links it, and loads and runs the result.

To run the program on a different platform, we do not have to re­write it (if it is correctly written). The same source codeis re­compiled for a different target.

As well as being partly platform­independent, a high level language allows us to focus on the logic of the problem solution, instead of the details of the machine we are using.

Java bytecode

Java uses a different approach from C. The reason is that Java was required to run on a wide range of platforms, without being re­compiled. That is, it should be possible to compile a Java program, and run it unchanged, on differentprocessors and different OS. How to do this? As follows:

1. A Java compiler converts source code into an intermediate form, called byte code.

2. Byte code executes on a Java Virtual Machine – a JVM.

3. A JVM is a piece of software. There are lots of JVMs – around 70. A different JVM is needed for every different platform.

4. A JVM is a 'virtual machine'. It appears to byte code running on it that it has a screen(maybe) and a mouse and keyboard and so on. In fact these are virtual.

5. The JVM maps the actual hardware and OS calls to thesevirtual resources. So when Java bytecode draws a window on the screen, it actually draws it on a virtual screen, whichthe JVM maps to the actual hardware screen.

How To Program © Walter Milner 2013                            Page 175 

Page 176: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

This means the same byte code will run the same (more or less) on any platform which has a JVM

How bytecode works

The utility javap, part of the JDK, lets us look at bytecode ina .class file. We start with a simple piece of source code:

public class Test {

public static void main(String[] args) { int t=0;for (int x=5; x<10; x++)t++;

}}

If this is compiled, then we go to the folder where Test.class is, then 'javap ­c Test' will display the byte code, like this: ( comments are mine )

walter@walter-s5-1030uk:~/eclipseworkspace/testJava/bin$ javap -c Test

Compiled from "Test.java"

public class Test extends java.lang.Object{

public Test(); // compiler generated no-arg constructor

Code:

0: aload_0

1: invokespecial#8; //Method java/lang/Object."<init>":()V

4: return

public static void main(java.lang.String[]);

Code:

0: iconst_0 // push 0 onto stack

1: istore_1 // pop value into variable 1. so t=0

2: iconst_5 // push 5 on stack

3: istore_2 // pop into variable 2. So x=5

4: goto 13 // go to 13

7: iinc 1, 1 // increment t

10: iinc 2, 1 // increment x

13: iload_2 // get variable 2 (which is x)

14: bipush 10 // push 10 onto stack

16: if_icmplt 7 // compare with value popped off stack,

// and go to 7 if not equal. IOW goto 7

// if x!=10

19: return

}

So bytecode makes extensive use of a stack. Here it is usingvariable 1 as t, and does t=0 by pushing 0 on the stack, then popping it off into variable 1. Similarly for initialising xat 5 in variable 2. The body of the loop, t++;, is line 7, and lines 13, 14 and 16 do the check x<10 to continue the  loop.

How To Program © Walter Milner 2013                            Page 176 

Page 177: Table of Contents Introduction.............................................7 The idea of Programming..........................9 Programming languages are formal

This is in effect assembly language, corresponding to the machine code, which is the actual byte code. But the machine that the byte code runs on is the virtual machine ofthe JVM, not directly on the processor with its registers.  

Why would you learn to program in Java bytecode? If you needed to write a JVM, for a new platform. Otherwise there is little point. Clearly, writing code in Java not bytecode is simpler, easier, faster and makes more sense than using bytecode. In other words, we can ignore how bytecode works, because it does not matter. We can abstract away the implementation mechanism for Java, and focus on writing the source code to formulate algorithmic solutions to problems.

Abstraction

You could learn more about writing assembler. But that is not what this text is about. Nor is it about bytecode.

It is about things called abstract data types, data structuresand algorithms. These are the same across programming languages, let alone platforms. In other words a tree, for example, is the same in assembler, C, Java and Java ­ it is language­agnostic.

There are two advantages to this approach. First is it makesthe ideas very powerful and useful, since we can use them in any language. It also makes it clearer, since we can focuson the idea, not how it is implemented on one processor.

This section has looked at how a Linux Intel/AMD computer works, as a machine. We can now park that idea, and look instead at data structures and algorithms in themselves, with an implementation in the high level language of Java, which will work the same on any machine.

This is the idea of abstraction. We ignore how the machine does it, in terms of registers and memory locations and OS calls. Instead we focus on a solution in terms of the problemand an algorithm to solve it.  

How To Program © Walter Milner 2013                            Page 177