Übung Informatik I - Programmierung - Blatt 7

Similar documents
7. The Recursion Theorem

7. The Recursion Theorem

Introduction to Programming (Java) 3/12

1 Trees. Listing 1: Node with two child reference. public class ptwochildnode { protected Object data ; protected ptwochildnode l e f t, r i g h t ;

CMSC 132, Object-Oriented Programming II Summer Lecture 6:

Lecture 14: Nov. 11 & 13

7. The Recursion Theorem

CMSC 132, Object-Oriented Programming II Summer Lecture 10:

Binary Search Trees. Motivation

Searching, mainly via Hash tables

Section Summary. Sequences. Recurrence Relations. Summations Special Integer Sequences (optional)

Introduction to Computer Programming, Spring Term 2018 Practice Assignment 5 Discussion: power(m,n) = m n

1 ListElement l e = f i r s t ; / / s t a r t i n g p o i n t 2 while ( l e. next!= n u l l ) 3 { l e = l e. next ; / / next step 4 } Removal

Recursion: Introduction and Correctness

Outline Resource Introduction Usage Testing Exercises. Linked Lists COMP SCI / SFWR ENG 2S03. Department of Computing and Software McMaster University

Tricks of the Trade in Combinatorics and Arithmetic

CSE373: Data Structures and Algorithms Lecture 3: Math Review; Algorithm Analysis. Catie Baker Spring 2015

Lecture 5: Sep. 23 &25

Mathematical Background. Unsigned binary numbers. Powers of 2. Logs and exponents. Mathematical Background. Today, we will review:

CS173 Running Time and Big-O. Tandy Warnow

Elementary Sorts 1 / 18

Administrivia. COMP9020 Lecture 7 Session 2, 2017 Induction and Recursion. Lecture 6 recap. Lecture 6 recap

Introduction to Computing II (ITI 1121) FINAL EXAMINATION

Algorithms and Data Structures

Thomas Jefferson Invitational Open in Informatics

CMSC 132, Object-Oriented Programming II Summer Lecture 12

Google Go illustrated on the basis of Fibonacci numbers

Lecture 4: Stacks and Queues

CS 61B Asymptotic Analysis Fall 2017

Introduction to Computing II (ITI 1121) FINAL EXAMINATION

Softwaretechnik. Lecture 13: Design by Contract. Peter Thiemann University of Freiburg, Germany

Softwaretechnik. Lecture 13: Design by Contract. Peter Thiemann University of Freiburg, Germany

Lisp Introduction. Dr. Neil T. Dantam. Spring CSCI-498/598 RPM, Colorado School of Mines. Dantam (Mines CSCI, RPM) Lisp Spring / 88

Object Oriented Software Design (NTU, Class Even, Spring 2009) Final Examination Problem Sheet TIME: 06/16/2009, 14:20 17:20

Motivation. Dictionaries. Direct Addressing. CSE 680 Prof. Roger Crawfis

Mathematical Induction

MATHEMATICAL OBJECTS in

Programming Abstractions

Topic 17. Analysis of Algorithms

1. Write a program to calculate distance traveled by light

Introduction to Algorithmic Complexity. D. Thiebaut CSC212 Fall 2014

Data Structure Lecture#4: Mathematical Preliminaries U Kang Seoul National University

CMSC 132, Object-Oriented Programming II Summer Lecture 11:

Lecture 5: Jun. 10, 2015

Recurrence Relations and Recursion: MATH 180

HW8. Due: November 1, 2018

Problem Set 1 Solutions

Data Structures and Algorithms

CS-140 Fall 2018 Test 2 Version Practice Nov. 12, Name:

Data Structures and Algorithms Winter Semester

SDS developer guide. Develop distributed and parallel applications in Java. Nathanaël Cottin. version

CSCB63 Winter Week 11 Bloom Filters. Anna Bretscher. March 30, / 13

CSE 311: Foundations of Computing. Lecture 26: Cardinality

Introduction to Computing II (ITI1121) FINAL EXAMINATION

Lecture 2. Fundamentals of the Analysis of Algorithm Efficiency

Quiz 1 Solutions. Problem 2. Asymptotics & Recurrences [20 points] (3 parts)

import java. u t i l. ;... Scanner sc = new Scanner ( System. in ) ;

Remainders. We learned how to multiply and divide in elementary

Section Summary. Sequences. Recurrence Relations. Summations. Examples: Geometric Progression, Arithmetic Progression. Example: Fibonacci Sequence

Lists, Stacks, and Queues (plus Priority Queues)

Binary addition example worked out

1 Closest Pair of Points on the Plane

Automatic Verification of Parameterized Data Structures

Solution suggestions for examination of Logic, Algorithms and Data Structures,

CSE 431/531: Analysis of Algorithms. Dynamic Programming. Lecturer: Shi Li. Department of Computer Science and Engineering University at Buffalo

Hoare Calculus and Predicate Transformers

Aside: Golden Ratio. Golden Ratio: A universal law. Golden ratio φ = lim n = 1+ b n = a n 1. a n+1 = a n + b n, a n+b n a n

Mathematical Background

Heaps and Priority Queues

Data Structures and Algorithms Chapter 2

CSCI Honor seminar in algorithms Homework 2 Solution

Running Time Evaluation

DNHI Homework 2 Solutions Recursion

Mathematical Induction

Axiomatic Semantics. Stansifer Ch 2.4, Ch. 9 Winskel Ch.6 Slonneger and Kurtz Ch. 11 CSE

Stacks. Definitions Operations Implementation (Arrays and Linked Lists) Applications (system stack, expression evaluation) Data Structures 1 Stacks

(a) Definition of TMs. First Problem of URMs

Sharing Objects. Pieter van den Hombergh. Fontys Hogeschool voor Techniek en Logistiek. February 15, 2017

Algorithm efficiency analysis

Insert Sorted List Insert as the Last element (the First element?) Delete Chaining. 2 Slide courtesy of Dr. Sang-Eon Park

Clock-driven scheduling

CS-140 Fall 2017 Test 1 Version Practice Practice for Nov. 20, Name:

= 1 when k = 0 or k = n. Otherwise, Fact 4.5 (page 98) says. n(n 1)(n 2) (n k + 3)(n k + 2)(n k + 1) (n k + 1)(n k + 2)(n k + 3) (n 2)(n 1) n

CSC 7101: Programming Language Structures 1. Axiomatic Semantics. Stansifer Ch 2.4, Ch. 9 Winskel Ch.6 Slonneger and Kurtz Ch. 11.

Data Structure Lecture#4: Mathematical Preliminaries U Kang Seoul National University

Introduction to Computing II (ITI 1121) MIDTERM EXAMINATION

3. Algorithms. What matters? How fast do we solve the problem? How much computer resource do we need?

Artificial Intelligence Chapter 7: Logical Agents

Part I: Definitions and Properties

Lecture 27: Theory of Computation. Marvin Zhang 08/08/2016

Advanced topic: Space complexity

Software Engineering

Lecture 2: Divide and conquer and Dynamic programming

CSE 20. Lecture 4: Introduction to Boolean algebra. CSE 20: Lecture4

Solving Recurrences. Lecture 23 CS2110 Fall 2011

Data Structures. Outline. Introduction. Andres Mendez-Vazquez. December 3, Data Manipulation Examples

The Viterbi Algorithm EECS 869: Error Control Coding Fall 2009

CSE 20 DISCRETE MATH. Fall

FPGA Resource Utilization Estimates for NI PXI-7854R. LabVIEW FPGA Version: 8.6 NI-RIO Version: 3.0 Date: 8/5/2008

Optimisation and Operations Research

Transcription:

RHEINISCH- WESTFÄLISCHE TECHNISCHE HOCHSCHULE AACHEN LEHR- UND FORSCHUNGSGEBIET INFORMATIK II RWTH Aachen D-52056 Aachen GERMANY http://programmierung.informatik.rwth-aachen.de LuFG Informatik II Prof. Dr. Jürgen Giesl Peter Schneider-Kamp, René Thiemann, Thomas Weiler Übung Informatik I - Programmierung - Blatt 7 (Lösungsvorschlag) Aufgabe 1 b) Stelligkeit: 419 c) ack(1, 100), ack(2, 100), ack(3, 8..15), ack(4, 0..1) d) Bit-Shifting: 2ms, wiederholtes Quadrieren: 1835ms, Einfache Iteration: 59585ms Aus ack(4, 2) = 2 10 19728 ergibt sich log 10 (ack(4, 3)) = log 10 (ack(3, ack(4, 2))) = log10 (2 2 1019728 ) = log 10 (2) 2 10 19728 = 6 10 19727 Folglich hat ack(4, 3) ungefähr 6 10 19727 viele Stellen. Fibonacci import java. math. B i g I n t e g e r ; * Implementation of the Fibonacci function with precise * numbers ( <code >java. math. BigInteger </ code >). The class provides a slow and a fast routine. * * @author thiemann * @version 28.11.2003 1

public class Fib { private f i n a l static B i g I n t e g e r zero = B i g I n t e g e r.zero; private f i n a l static B i g I n t e g e r one = B i g I n t e g e r.one; * Computes the Fibonacci function in the naive way * @param n the input value as integer * @return the precise value of fib(n) public static B i g I n t e g e r f i b S i m p l e ( int n ) { i f ( n <= 0) return zero ; i f ( n == 1) return one ; return ( f i b S i m p l e (n 1). add ( f i b S i m p l e (n 2) ) ) ; * Computes the Fibonacci function in time linear to n * @param n the input value as integer * @return the precise value of fib(n) public static B i g I n t e g e r f i b F a s t ( int n ) { return f i b F a s t 2 ( n, zero, one ) ; * idea: * the first parameter stores the number of necessary iterations * the second parameter is fib(i) * the third one is fib(i+1) private static B i g I n t e g e r f i b F a s t 2 ( int n, B i g I n t e g e r f i b i, B i g I n t e g e r f i b i p l u s 1 ) { i f ( n <= 0) return f i b i ; return f i b F a s t 2 ( n 1, f i b i p l u s 1, f i b i. add ( f i b i p l u s 1 ) ) ; Ackermann import java. math. B i g I n t e g e r ; 2

* The Ack class computes in various ways the Ackermann function * call the main routine with the specific calculation method as * a simple interface. ( the different calculation methods have very different * time and space consumption) * <p> * Beware of values ack(x,y) with x >= 5 or with x=4 and y >=3 * * @author thiemann * @version 1.0 (28.11.2003) public class Ack { * start simple interface asking for values x and y and * then computes and outputs ack(x,y); * additionally the computation time is displayed * @param args There should be passed one argument: the method. * Valid methods ( from slow to fast) are " recursive", " iterative ", "iterativenolist", "direct" public static void main ( S t r i n g [ ] args ) { i f ( args. length! = 1 ) { System. e r r. p r i n t l n ( "Please specify exact one method" ) ; return ; S t r i n g method = args [ 0 ] ; S t r i n g [ ] methods = {"recursive", "iterative", "iterativenolist", " direct" ; for ( int i = 0 ; i < methods. length ; i ++) { i f ( method. e q u a l s ( I n t e g e r. t o S t r i n g ( i +1)) method. e q u a l s ( methods [ i ] ) ) { System. out. p r i n t l n ( "Method: "+methods [ i ] ) ; System. out. p r i n t ( "x: " ) ; int x = IO. readint ( ) ; System. out. p r i n t ( "y: " ) ; int y = IO. readint ( ) ; int a ; B i g I n t e g e r biga ; long time ; time = System. c u r r e n t T i m e M i l l i s ( ) ; switch ( i ) { case 0 : a = ack ( x, y ) ; time += System. c u r r e n t T i m e M i l l i s ( ) ; System. out. p r i n t l n ( a ) ; break ; 3

case 1 : a = a c k i t e r ( x, y ) ; time += System. c u r r e n t T i m e M i l l i s ( ) ; System. out. p r i n t l n ( a ) ; break ; case 2 : a = a c k i t e r 2 ( x, y ) ; time += System. c u r r e n t T i m e M i l l i s ( ) ; System. out. p r i n t l n ( a ) ; break ; case 3 : biga = a c k d i r e c t ( x, y ) ; time += System. c u r r e n t T i m e M i l l i s ( ) ; System. out. p r i n t l n ( biga ) ; int length = biga. t o S t r i n g ( ). length ( ) ; i f ( length > 80) { System. out. p r i n t l n ( "Length: " + length ) ; System. out. p r i n t l n ( "Time: "+time+"ms" ) ; return ; System. e r r. p r i n t l n ( "Wrong method! Please choose one of \n" ) ; for ( int i = 0 ; i < methods. length ; i ++) { System. e r r. p r i n t l n ( i+1+") "+methods [ i ] ) ; * computes the Ackermann function ack(x,y) in a recursive way * @param x the first argument to ack * @param y the second argument to ack * @return the value of ack(x,y) as integer public static int ack ( int x, int y ) { i f ( x == 0) return ( y+1) ; i f ( y == 0) return ack ( x 1,1) ; return ack ( x 1, ack ( x, y 1) ) ; * computes the Ackermann function ack(x,y) in an iterative way; * here we use lists to store all the values of ack * ( ack(x,y) space consumption) * @param x the first argument to ack * @param y the second argument to ack * @return the value of ack(x,y) as integer 4

public static int a c k i t e r ( int x, int y ) { // initialize fields and lists int [ ] ack want = new int [ x +1]; DoubleLinkedList [ ] v a l u e s = new DoubleLinkedList [ x +1]; I n t e g e r t e s t ; for ( int i x =0; i x <= x ; i x++) { ack want [ i x ] = 1; v a l u e s [ i x ] = new DoubleLinkedList ( ) ; ack want [ x ] = y ; // initialize loop int i x = x ; int i y = y ; // outer loop for x i x l o o p : while ( i x <= x ) { // inner loop for y i y l o o p : while ( v a l u e s [ i x ]. length ( ) <= ack want [ i x ] ) { i y = v a l u e s [ i x ]. length ( ) ; // case 1 i f ( i x == 0) { v a l u e s [ i x ]. addend ( i y + 1) ; continue ; // case 2 i f ( i y == 0) { t e s t = v a l u e s [ ix 1]. getpos ( 1 ) ; i f ( t e s t! = null ) { // value present v a l u e s [ i x ]. addend ( t e s t. intvalue ( ) ) ; continue ; ack want [ ix 1] = 1; i x = 1; continue i x l o o p ; 5

// case 3 // we know by construction that a(ix,y-1) is present int ay 1 = v a l u e s [ i x ]. getpos ( iy 1). intvalue ( ) ; t e s t = v a l u e s [ ix 1]. getpos ( ay 1 ) ; i f ( t e s t! = null ) { // value present v a l u e s [ i x ]. addend ( t e s t. intvalue ( ) ) ; continue ; // enforce computation of a(ix-1, ay_1) ack want [ ix 1] = ay 1 ; i x = 1; continue i x l o o p ; // so current ix level completed i x += 1; continue ; return v a l u e s [ x ]. getpos ( y ). intvalue ( ) ; * computes the Ackermann function ack(x,y) in an iterative way; * here we only store the last computed values a(x,i) for each x * ( linear space consumption in x) * @param x the first argument to ack * @param y the second argument to ack * @return the value of ack(x,y) as integer public static int a c k i t e r 2 ( int x, int y ) { int [ ] ack want = new int [ x +1]; int [ ] ack have = new int [ x +1]; int [ ] a c k l a s t = new int [ x +1]; for ( int i x =0; i x <= x ; i x++) { ack want [ i x ] = 1; ack have [ i x ] = 1; a c k l a s t [ i x ] = 1; int i x = x ; int i y = y ; ack want [ x ] = y ; i x l o o p : while ( i x <= x ) { i y l o o p : while ( ack have [ i x ] < ack want [ i x ] ) { 6

i y = ack have [ i x ] + 1 ; // case 1 i f ( i x == 0) { a c k l a s t [ i x ] = i y + 1 ; ack have [ i x ] = i y ; continue ; // case 2 i f ( i y == 0) { i f ( ack have [ ix 1] >= 1) { // value present a c k l a s t [ i x ] = ack have [ i x ] = i y ; continue ; ack want [ ix 1] = 1; i x = 1; continue i x l o o p ; a c k l a s t [ ix 1]; // case 3 // we know by construction that a(ix,y-1) is present and is stored in ack_last[ix] int ay 1 = a c k l a s t [ i x ] ; i f ( ack have [ ix 1] >= ay 1 ) { // value present a c k l a s t [ i x ] = a c k l a s t [ ix 1]; ack have [ i x ] = i y ; continue ; // enforce computation of a(ix-1, ay_1) ack want [ ix 1] = ay 1 ; i x = 1; continue i x l o o p ; // so current ix level completed i x += 1; continue ; return a c k l a s t [ x ] ; * Easy access to BigIntegers 7

private static B i g I n t e g e r tobig ( int i ) { return new B i g I n t e g e r ( I n t e g e r. t o S t r i n g ( i ) ) ; private f i n a l static B i g I n t e g e r zero = tobig ( 0 ) ; private f i n a l static B i g I n t e g e r one = tobig ( 1 ) ; private f i n a l static B i g I n t e g e r two = tobig ( 2 ) ; private f i n a l static B i g I n t e g e r t h r e e = tobig ( 3 ) ; private f i n a l static B i g I n t e g e r maxint = tobig ( I n t e g e r.max VALUE) ; * Exponentation ( simple version) private static B i g I n t e g e r pow2simple ( B i g I n t e g e r x ) { B i g I n t e g e r r e s = one ; while ( x. compareto ( zero ) > 0) { r e s = r e s. multiply ( two ) ; x = x. s u b t r a c t ( one ) ; return r e s ; * Exponentation with repeated squaring * without bit- shifting operations private static B i g I n t e g e r pow2square ( B i g I n t e g e r x ) { B i g I n t e g e r r e s = one ; B i g I n t e g e r base = two ; while ( x. compareto ( zero ) > 0) { i f ( x. and ( one ). e q u a l s ( one ) ) { r e s = r e s. multiply ( base ) ; base = base. multiply ( base ) ; x = x. d i v i d e ( two ) ; return r e s ; * Exponentation with base 2 by bit- shifting private static B i g I n t e g e r pow2shift ( B i g I n t e g e r x ) { B i g I n t e g e r erg = one ; while ( x. compareto ( maxint ) > 0) { 8

erg = erg. s h i f t L e f t ( I n t e g e r.max VALUE) ; x = x. s u b t r a c t ( maxint ) ; erg = erg. s h i f t L e f t ( x. intvalue ( ) ) ; return erg ; * Choose method for potentiation private static B i g I n t e g e r pow2( B i g I n t e g e r x ) { // return pow2simple(x); // return pow2square(x); return pow2shift ( x ) ; * Computing towers of 2 s private static B i g I n t e g e r tower2 ( int h ) { B i g I n t e g e r r e s = one ; while ( h > 0) { r e s = pow2( r e s ) ; h ; return r e s ; * computes the Ackermann function ack(x,y) in an explicit way * @param x the first argument to ack * @param y the second argument to ack * @return the value of ack(x,y) as BigInteger public static B i g I n t e g e r a c k d i r e c t ( int x, int y ) { i f ( x == 5 && y == 0) { x = 4 ; y = 1 ; i f ( x == 0) return tobig ( y+1) ; i f ( x == 1) return tobig ( y+2) ; i f ( x == 2) return tobig (2 y+3) ; i f ( x == 3) return pow2( tobig ( y+3)). s u b t r a c t ( t h r e e ) ; i f ( x == 4 && y <= 2) return tower2 ( y+3). s u b t r a c t ( t h r e e ) ; 9

// all other values are to big to be computed System. e r r. p r i n t l n ( "Computing..." ) ; for ( int i = 0 ; i < 20000; i++) { System. e r r. p r i n t ( "." ) ; System. e r r. p r i n t l n ( "\n1. Buy me much more memory" ) ; System. e r r. p r i n t l n ( "2. Buy me a very fast processor" ) ; System. e r r. p r i n t l n ( "3. Attach a display of at least 18*10^19727 * 8 pixel to display the number" ) ; System. e r r. p r i n t l n ( " (If we have 10 pixels per mm, then the width is only 6*10^19701 million light years)" ) ; System. e r r. p r i n t l n ( "4. Wait for output and take your time to read it" ) ; System. e r r. p r i n t l n ( "\notherwise I give up here," ) ; System. e r r. p r i n t l n ( "Your computer" ) ; System. e x i t ( 0 ) ; return null ; Aufgabe 2 * Double- linked list of integers with constant access * functions on both ends and constant length computation. * Direct access to elements in the middle costs at most * length/2 iterations. * Duplicates are allowed. * The implementation bases on the <code >Elem </ code > * data structure. * * @author thiemann * @version 1.12.2003 * @see Elem public class DoubleLinkedList { private Elem head ; // head of the list; null, if list is empty private Elem end ; // end of the list; null, if list is empty private int length ; // the current list-length 10

* Standard- Representation ( linear time) * @return a String representing the list from head to end public S t r i n g t o S t r i n g ( ) { return t o S t r i n g ( this. head, f a l s e ) ; * Standard- Representation of the reversed list ( linear time) * @return a String representing the list from end to head public S t r i n g t o S t r i n g R e v e r s e ( ) { return t o S t r i n g ( this. head, true ) ; * produces a string representing the list beginning at * the given parameter " e" in given direction private S t r i n g t o S t r i n g ( Elem e, boolean r e v e r s e ) { i f ( e == null ) { return "" ; else { int v = e. getvalue ( ) ; i f ( r e v e r s e ) { return ( t o S t r i n g ( e. getright ( ), r e v e r s e )+" "+v ) ; else { return ( v+" "+t o S t r i n g ( e. getright ( ), r e v e r s e ) ) ; * Computes the list - length ( in constant time) * @return the list length public int length ( ) { return this. length ; 11

* Creates an empty list public DoubleLinkedList ( ) { this. head = null ; this. end = null ; this. length = 0 ; * computes the value of the * first element of the list, if this exists ( constant time) * @return null, if the list is empty; the first element otherwise public I n t e g e r gethead ( ) { return getpos ( 0 ) ; * computes the value of the last element of the list, * if this exists ( constant time) * @return null, if the list is empty; the last element otherwise public I n t e g e r getend ( ) { return getpos ( this. length 1) ; * computes the value of the element at position p of the list. Here, we * start counting from 0, so a valid range for p is 0 <= p < length * ( linear time, but at most length/2 iterations) * @return null, if the position is out of bounds, or otherwise * the element at the given position public I n t e g e r getpos ( int p ) { Elem e = getpospriv ( p) ; i f ( e == null ) { return null ; return new I n t e g e r ( e. getvalue ( ) ) ; 12

* Adds the value v in front of the list ( in constant time) * @param v the integer to be added public void addhead( int v ) { Elem e = new Elem( v, null, head ) ; i f ( this. head! = null ) { // non-empty list this. head. s e t L e f t ( e ) ; this. head = e ; else { // empty list head = e ; end = e ; this. length ++; * Adds the value v at the end of the list ( in constant time) * @param v the integer to be added public void addend ( int v ) { Elem e = new Elem( v, end, null ) ; i f ( this. end! = null ) { // non-empty list this. end. setright ( e ) ; this. end = e ; else { // empty list this. head = e ; this. end = e ; this. length ++; * adds the value v before element at position p; * to store an element at the end, p should be length; * look at <code >getpos </ code > for more information * about positions. * * @param v the value to be inserted 13

* @param p insert before this element; 0 <= p <= length * @return true, if v was inserted; false, otherwise public boolean addpos ( int v, int p ) { // check for valid position i f ( p < 0 p > this. length ) { return f a l s e ; // deal with special cases i f ( p == 0) { addhead( v ) ; else i f ( p == this. length ) { addend ( v ) ; else { // now, we have to add the element in the middle // so, no update of head or end has to be done! // catch the right element Elem curr = getpospriv ( p 1) ; // and update all pointers from the elements Elem e = new Elem( v, curr, curr. getright ( ) ) ; curr. setright ( e ) ; e. getright ( ). s e t L e f t ( e ) ; this. length ++; return true ; * get the element at position p starting from the best side * null, if p is not valid private Elem getpospriv ( int p ) { // position valid? i f ( p < 0 p >= this. length ) return null ; // which way boolean forward = this. length p > p ; // start iteration i f ( forward ) { return DoubleLinkedList. getpos (p, forward, this. head ) ; else { return DoubleLinkedList. getpos ( this. length p 1, forward, this. end ) ; 14

* walks count steps from current Element in direction * and returns the element at this position private static Elem getpos ( int count, boolean forward, Elem c u r r e n t ) { i f ( count == 0) { return c u r r e n t ; else i f ( forward ) { return getpos ( count 1, forward, c u r r e n t. getright ( ) ) ; else { return getpos ( count 1, forward, c u r r e n t. g e t L e f t ( ) ) ; * searches for the value v in forward direction, or * backward direction, if " forward" = false private Elem search ( int v, boolean forward ) { i f ( forward ) { return DoubleLinkedList. searchf ( v, this. head ) ; else { return DoubleLinkedList. searchb ( v, this. end ) ; * searches for v beginning from current in forward direction private static Elem searchf ( int v, Elem c u r r e n t ) { // value found? i f ( c u r r e n t. getvalue ( ) == v ) { return c u r r e n t ; // reached end? else i f ( c u r r e n t. getright ( )! = null ) { // no, then iterate return searchf ( v, c u r r e n t. getright ( ) ) ; else { 15

// yes, then the value is not present return null ; * searches for v beginning from current in backward direction private static Elem searchb ( int v, Elem c u r r e n t ) { // value found? i f ( c u r r e n t. getvalue ( ) == v ) { return c u r r e n t ; // reached end? else i f ( c u r r e n t. g e t L e f t ( )! = null ) { // iterate return searchb ( v, c u r r e n t. g e t L e f t ( ) ) ; else { // failure return null ; * deletes the element e from the list private boolean d e l e t e ( Elem e ) { // delete null- element can not be done i f ( e == null ) return f a l s e ; // update with left neighbor // special case head- element i f ( e == this. head ) { this. head = e. getright ( ) ; // test, if head was not the only element i f ( this. head! = null ) { this. head. s e t L e f t ( null ) ; else { // usual left element e. g e t L e f t ( ). setright ( e. getright ( ) ) ; // update with right neighbor 16

// special case end- element i f ( e == this. end ) { this. end = e. g e t L e f t ( ) ; // test, if end was not the only element i f ( this. end! = null ) { this. end. setright ( null ) ; else { // usual right element e. getright ( ). s e t L e f t ( e. g e t L e f t ( ) ) ; this. length ; return true ; * Deletes the head of the list * (constant time) * @return true, if there was a head ( if list was not empty); * false, otherwise public boolean deletehead ( ) { return d e l e t e ( this. head ) ; * Deletes the end of the list * (constant time) * @return true, if there was a end ( if list was not empty); * false, otherwise public boolean deleteend ( ) { return d e l e t e ( this. end ) ; * Deletes the first occurence of the value v in the list * (linear time) * @param v the value to be deleted * @return true, iff something was deleted public boolean d e l e t e F i r s t ( int v ) { Elem e = search ( v, true ) ; 17

return d e l e t e ( e ) ; * Deletes the last occurence of the value v in the list * (linear time) * @param v the value to be deleted * @return true, iff something was deleted public boolean d e l e t e L a s t ( int v ) { Elem e = search ( v, f a l s e ) ; return d e l e t e ( e ) ; * deletes all elements with value v in the list * (linear time) * @param v the value to be deleted * @return the number of elements that have been deleted public int d e l e t e A l l ( int v ) { return d e l e t e A l l ( v, this. head ) ; * delete all elements that have value v * beginning from current, iterating in forward * direction * current must be non- null! private int d e l e t e A l l ( int v, Elem c u r r e n t ) { i f ( c u r r e n t == null ) return 0 ; // fetch next element v c u r r e n t = DoubleLinkedList. searchf ( v, c u r r e n t ) ; // found something? i f ( c u r r e n t! = null ) { // yes, then delete and look further d e l e t e ( c u r r e n t ) ; return (1+ d e l e t e A l l ( v, c u r r e n t. getright ( ) ) ) ; // no, then abort 18

return 0 ; * tests, whether the value v is stored in the list * @param v the test value * @return true, iff v was in the list public boolean elem ( int v ) { // direction does not matter Elem e = search ( v, true ) ; return ( e! = null ) ; 19