Question

In: Computer Science

For all code assignments there should be exhaustive test code which takes it input from stdin....

For all code assignments there should be exhaustive test code which takes it input from stdin. Your code should be reasonably efficient - it should not have big-Oh larger than what would be expected from good implementation

Q1. Implement a double linked list with a sentinel element. The API should have four methods (no more) to: i) A method to create a new list instantiated with some type of elements (data stored in the list) defined at the time the list is created ii) A method to insert an element at the beginning of the list iii) A method to insert an element at the end of the list and a method to remove and return the first element in the list iv) A method to remove and return the last element of the list and You should calculate the Big-Oh complexities for insertion and removal of elements.

-----------------------------------------------------------------------------------------

Kindly answer all 4 sub parts. Program: Java, no prebuild libiary.

Solutions

Expert Solution

Please find all the explanation to the code within the code itself as comments.

Please note that because the constraint of the problem was to create no more than 4 methods, we have combined the operations performed by the third part, "A method to insert an element at the end of the list and a method to remove and return the first element in the list" into a single function. But, we have also cleanly separated the code for the two operations, so, if you want them to be two different functions, you may create two functions like this:

1. insertAtEnd (): This function will insert the argument provided at the end of the list.

2. removeAndReturnFromBeginning (): This function will remove the Node from the beginning of the list and returns the reference to it.

TAKING INPUT:

Taking the data for our DoublyLinkedList can be of different types.

1. We may use to code to take the input from the user within our DoublyLinkedList () constructor like this:

    public DoublyLinkedList () {
                        
                // set head and tail to null initially
                head = null;
                tail = null;

                // we will create a Scanner object 
                // to take the input from the user
                Scanner scanner = new Scanner (System.in);

                // we will take the input from the user
                String input = scanner.next ();

                int data = 0;

                // create a new Node reference
                Node newNode = null;

                // we will take the input from the user 
                // until we encounter "exit"
                while (input.equals("exit") == false) {
                                
                        // convert the string to integer
                        data = Integer.parseInt (input);
                        
                        // create a new Node
                        newNode = new Node (data);

                        // if the head Node is null, that means
                        // our list is empty
                        if (head == null) {
                                // as there is only one Node 
                                // in our list for now, 

                                // both head and tail point to that
                                head = newNode;
                                tail = newNode;
                        }

                        // but, if our list is not empty
                        else {

                                // we will concatenate the 
                                // incoming node at the end

                                // set newNode as the next of current tail
                                tail.next = newNode;
                                // set the previous of newNode to current tail
                                newNode.previous = tail;

                                // because, newNode is now the last element
                                // update tail reference
                                tail = newNode;
                        }

                        // take input from the user
                        input = scanner.next();
                }
        }

2. Or we can provide a list to our constructor function using which it will on its own fill-up the DoublyLinkedList. Like this:

    public DoublyLinkedList (int [] input) {
                        
                // set head and tail to null initially
                head = null;
                tail = null;

                int i = 0;

                // create a new Node reference
                Node newNode = null;

                // we will take the input from the user 
                // until we encounter "exit"
                while (i < input.length) {
                                
                        // create a new Node
                        newNode = new Node (input[i]);

                        // if the head Node is null, that means
                        // our list is empty
                        if (head == null) {
                                // as there is only one Node 
                                // in our list for now, 

                                // both head and tail point to that
                                head = newNode;
                                tail = newNode;
                        }

                        // but, if our list is not empty
                        else {

                                // we will concatenate the 
                                // incoming node at the end

                                // set newNode as the next of current tail
                                tail.next = newNode;
                                // set the previous of newNode to current tail
                                newNode.previous = tail;

                                // because, newNode is now the last element
                                // update tail reference
                                tail = newNode;
                        }

                        // increment the iterator
                        i += 1;
                }
        }

Because in questions, we are given to use the list form, we will use that in our code.

As it was not specified in the problem statement to put the test code into the same file, we have created two files, DoublyLinkedList.java and TestCode.java to keep things organized. ( If you want the test code into the same file, then, just copy and paste the main function from the file TestCode.java to DoublyLinkedList.java within the class DoublyLinkedList. )

Here is the full code:

DoublyLinkedList

import java.util.*;

// we will create a class
// for the nodes in our DoublyLinkedList
class Node {
                
        // the attribute, which will 
        // hold the data 
        public int data;

        // reference to next node to point to 
        // the node next to it in the list
        public Node next;

        // reference to previous node to point to
        // the node previous to it in the list
        public Node previous;

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

public class DoublyLinkedList {

        // we will have a reference to 
        // the head Node in our class 
        private Node head;

        // we will have a reference to
        // the tail Node in our class
        private Node tail;
                
        // as we require a method to create a new list 
        // instantiated with some type of elements 
        // defined at the time the list is created and 
        // for that, we can use a constructor of  class

        // you may change this into something like 
        // createDoublyLinkedList() function rather than a 
        // constructor, if that's required
         
        public DoublyLinkedList (int [] input) {
                        
                // set head and tail to null initially
                head = null;
                tail = null;

                int i = 0;

                // create a new Node reference
                Node newNode = null;

                // we will take the input from the user 
                // until we encounter "exit"
                while (i < input.length) {
                                
                        // create a new Node
                        newNode = new Node (input[i]);

                        // if the head Node is null, that means
                        // our list is empty
                        if (head == null) {
                                // as there is only one Node 
                                // in our list for now, 

                                // both head and tail point to that
                                head = newNode;
                                tail = newNode;
                        }

                        // but, if our list is not empty
                        else {

                                // we will concatenate the 
                                // incoming node at the end

                                // set newNode as the next of current tail
                                tail.next = newNode;
                                // set the previous of newNode to current tail
                                newNode.previous = tail;

                                // because, newNode is now the last element
                                // update tail reference
                                tail = newNode;
                        }

                        // increment the iterator
                        i += 1;
                }
        }

        // this method to insert an element at the beginning of the list
        public void insertAtBeginning (int data) {
                        
                // we will create a new Node with the given data 
                Node newNode = new Node (data);

                // because this node must be the head now

                // we will set the next of this node to the current head
                newNode.next = head;
                // we will set the previous of head to the new Node
                head.previous = newNode;

                // update the head reference to the new Node
                head = newNode;
        }

        // this method is used: 
        // 1. to insert an element at the end of the list 
        // 2. to remove and return the first element in the list

        public Node insertAtEndAndRemoveFromBeginning (int insertionData) {
                        
                // INSERTION AT THE END

                // because we have the reference to the tail of our list
                // we can use it to insert our data at the end

                // create a new node
                Node newNode = new Node (insertionData);

                // set newNode as the next of current tail
                tail.next = newNode;
                // set the previous of newNode to current tail
                newNode.previous = tail;

                // because, newNode is now the last element
                // update tail reference
                tail = newNode;


                // REMOVINT AND RETURN FROM THE BEGINNING

                // essentially, we want to remove and return the current head from the list
                // save the current head into a Node reference
                Node toReturn = head;

                // in order to remove the head node
                // make the Node next to head as new head
                head = head.next;

                // the previous of the new head would be null
                head.previous = null;

                // return the reference to the removed Node
                return toReturn;
        }

        // A method to remove and return the last element of the list
        public Node removeAndReturnLast () {
                        
                // to remove the last element from the list
                // we would need to manipulate some references related to second last Node

                // therefore, we will save the reference to the second last Node
                Node secondLast = tail.previous;

                // we will save the reference to the tail Node 
                // in order later return it
                Node toReturn = tail;

                // after removing the last Node, secondLast Node will be the new last Node
                // therefore, we will set the next of secondLast Node as null
                secondLast.next = null;

                // return the reference to the removed node
                return toReturn;
        }
}


TestCode

As specified in the problem statement, we have written an exhaustive test code, covering all the functions and analyzing the contents of the list before and after they have been called.

import java.util.*;

public class TestCode {

        // print function to look at the data after manipulation
        public static void print (DoublyLinkedList dll) {
                        
                Node ptr = dll.head;

                System.out.println ();
                while (ptr != null) {
                        System.out.print (ptr.data + " ");
                        ptr = ptr.next;
                }
                System.out.println ();
        }
                
        public static void main (String [] args) {
                        
                // create a Scanner object for taking input
                Scanner scanner = new Scanner (System.in);

                System.out.println ("\nEnter the size of the array: ");
                // get the size of array from the user
                int n = scanner.nextInt ();

                // create an array of size n
                int [] arr = new int[n];

                System.out.println ("\nEnter the elements of the array: ");
                // fill in the array with user inputs
                for (int i = 0; i < n; ++i) {
                        arr[i] = scanner.nextInt ();
                }

                DoublyLinkedList dll = new DoublyLinkedList (arr);

                System.out.println ("\nEnter the value you want to insert at the beginning: ");
                int data = scanner.nextInt ();

                System.out.println ("\nPrinting before insertAtBeginning ()");
                print (dll);

                dll.insertAtBeginning (data);

                System.out.println ("\nPrinting after insertAtBeginning ()");
                print (dll);


                System.out.println ("\nEnter the value you want to insert at end: ");
                data = scanner.nextInt();

                System.out.println ("\nPrinting before insertAtBeginning ()");
                print (dll);

                Node node = dll.insertAtEndAndRemoveFromBeginning (data);
                System.out.println ("\nPrinting the data of the node removed from beginning: " + node.data);

                System.out.println ("\nPrinting after insertAtEndAndRemoveFromBeginning ()");
                print (dll);

                System.out.println ("\nPrinting before insertAtBeginning ()");
                print (dll);

                node = dll.removeAndReturnLast ();
                System.out.println ("\nPrinting the data of the node removed from beginning: " + node.data);

                System.out.println ("\nPrinting after removeAndReturnLast ()");
                print (dll);
        }
}

Please refer to the screenshots of the code at the end for understanding indentation.

TIME COMPLEXITY OF INSERTIONS AND DELETIONS

Let's analyze the time complexities of our insertion and deletion algorithms.

1. insertAtBeginning(): In this, we have manipulated only the first node, the head node of the linked lists. In total, we have 4 assignment statements in this function and all of them are of constant time, therefore, the time complexity of this function is:

2. insertAtEndAndRemoveFromBeginning(): In this, we have used both the head and the tail for deletion and insertion respectively. In here as well, all the operations were only assignments, there were no loops or anything. There were some if-else conditional statements as well, and they are also of constant time. Therefore, the time complexity of this function is:

3. removeAndReturnLast(): In this, we first found the reference to the second last node by using the previous reference of the last node, and this was, indeed, a constant time operation. Like in the previous two functions, we have manipulated some references to delete the last element. Therefore, the time complexity of this function is also:

Please note that all the insertions and deletions at the beginning were possible in O(1), because, we have access to the head node, while, all the insertions and deletions at the end were possible in O(1), because, we have access to the previous node.

Let's look at an input-output for the above code:


Related Solutions

C++ Create the code Read  numbers from stdin and print their sum to stdout. Input Format One...
C++ Create the code Read  numbers from stdin and print their sum to stdout. Input Format One line that contains  space-separated integers:a , b, c and . Constraints 1≤ a,b,c ≤1000 Output Format Print the sum of the three numbers on a single line. Sample Input 1 2 7 Sample Output 10 Explanation The sum of the three numbers is 1+2+7=10
Write an asssembly languaage (805l) code for EDSIM5I that takes the input from the # keypad...
Write an asssembly languaage (805l) code for EDSIM5I that takes the input from the # keypad to and output to the liquid crystal display.
Code in Java Write a recursive method smallestNumber which takes an ArrayList of Integers as input...
Code in Java Write a recursive method smallestNumber which takes an ArrayList of Integers as input and returns the smallest number in the array. You can use a helper method if needed. Write a main method that asks the user for a series of numbers, until the user enters a period. Main should create an ArrayList of these Integers and call smallestNumber to find the smallest number and print it. Input Format A series of integers Constraints None Output Format...
Code is in C Write a program that reads integers from stdin. Once it reaches the...
Code is in C Write a program that reads integers from stdin. Once it reaches the * end of the input, it prints the smallest absolute value among those * of the numbers it read. * * For example, if * 4, 6 -3, 3, -2, 13, -4 * are read from stdin, the program should print 2. * * If the end of file is reached before any integer is seen, the * number printed should be INT_MAX (defined...
Write a Java test program, all the code should be in a single main method, that...
Write a Java test program, all the code should be in a single main method, that prompts the user for a single character. Display a message indicating if the character is a letter (a..z or A..Z), a digit (0..9), or other. Java's Scanner class does not have a nextChar method. You can use next() or nextLine() to read the character entered by the user, but it is returned to you as a String. Since we are only interested in the...
Write a VHDL code for a 4-bit comparator which takes two 4-bit input values and (0.5)...
Write a VHDL code for a 4-bit comparator which takes two 4-bit input values and (0.5) determines whether the numbers are equal. 2. 2. Write a structural VHDL code to implement the circuit of Fig. 2, using the components (0.5) developed in 1.3 and 2.1. 2. 3. Write a VHDL test bench for the above and verify by simulation. (0.5) 2. 4. Implement the design in an FPGA (Note: You may need a `clock manager' to reduce (1.0) the clock...
Write a short C++ program that takes all the lines input to standard input and writes...
Write a short C++ program that takes all the lines input to standard input and writes them to standard output in reverse order. That is, each line is output in the correct order, but the ordering of the lines is reversed. Please use vector datatype standaard library #include <vector> Thanks
Write a Python program which takes a set of positive numbers from the input and returns...
Write a Python program which takes a set of positive numbers from the input and returns the sum of the prime numbers in the given set. The sequence will be ended with a negative number.
Write a program which reads an input file. It should assume that all values in the...
Write a program which reads an input file. It should assume that all values in the input file are integers written in decimal. Your program should read all integers from the file and print their sum, maximum value, minimum value, and average. Use the FileClient class here (from a previous reading) as an example. You'll need to create a file to be used as input to test your program, as well. Your program should work whether the integers are separated...
Write an R function that conducts a normality test as follows: it takes as input a...
Write an R function that conducts a normality test as follows: it takes as input a data set, calculates a bootstrap confidence interval for the skewness, calculates a bootstrap confidence interval for the kurtosis, then sees if 0 is in the skewness interval and 3 is in the kurtosis interval. If so, your routine prints that the data is normally distributed, otherwise your routine should print that the data is not normally distributed. Test your routine on random data from...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT