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...
Must be written in JAVA Code Write a program that takes a whole number input from...
Must be written in JAVA Code Write a program that takes a whole number input from a user and determines whether it’s prime. If the number is not prime, display its unique prime factors. Remember that a prime number’s factors are only 1 and the prime number itself. Every number that’s not prime has a unique prime factorization. For example, consider the number 54. The prime factors of 54 are 2, 3, 3 and 3. When the values are multiplied...
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 code that takes the initial velocity and angle as an input and outputs the...
Write a code that takes the initial velocity and angle as an input and outputs the maximum height of the projectile and its air time. Follow the pseudo code below. This will not be provided in as much detail in the future so you’ll have to provide pseudocode or a flowchart to showcase your logic. For this first assignment though, the logic is laid out below with some indented more detailed instructions. PROGRAM Trajectory: Establish the User Interface (Typically referred...
Answer in Python: show all code 3) Modify your code to take as input from the...
Answer in Python: show all code 3) Modify your code to take as input from the user the starting balance, the starting and ending interest rates, and the number of years the money is in the account. In addition, change your code (from problem 2) so that the program only prints out the balance at the end of the last year the money is in the account. (That is, don’t print out the balance during the intervening years.) Sample Interaction:...
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...
MATLAB Write a code that takes the initial velocity and angle as an input and outputs...
MATLAB Write a code that takes the initial velocity and angle as an input and outputs the maximum height of the projectile and its air time. Follow the pseudo code below. This will not be provided in as much detail in the future so you’ll have to provide pseudocode or a flowchart to showcase your logic. For this first assignment though, the logic is laid out below with some indented more detailed instructions. PROGRAM Trajectory: Establish the User Interface (Typically...
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...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT