How to recursively concatenate a list of string elements - java

I am looking at examples getting ready for an exam, and frankly, I am not very good with either recursion or lists, but particularly lists.
A node class is given, it will hold strings (not generic) write a recursive java function called concat that takes a node representing the head of a linked list and returns a string representing the concatenation of all the elements of the list if the list is empty the string should be as well.
Any help would be appreciated.
(The following is what I had type before I asked the question:)
public static String FindConcat(Node head) {
String s = "";
if(head == null) return s;
else if(head.next = null) {
s += head.data;
return s;
}
else {
}
}
Thanks for the repsonses.

In this case what recursion is finding the base case and how to "devide" the data down to this base case. So first define your "base case".
Base case: argument to the function is null
Till you get the the base case, append the text of the node and skip the first element
This is your method:
public static String FindConcat(Node head) {
if (head == null)
return ""; // base case
// devide it down (run recursive FindConcat on the _next_ node)
return head.data + FindConcat(head.next);
}
This simple example will print hello this is a linked list:
public class Test {
// this is a very basic Node class
static class Node {
String text;
Node next;
public Node(String text) {
this.text = text;
}
// used for building the list
public Node add(String text) {
next = new Node(text);
return next;
}
}
// this is the recursive method concat
public static String concat(Node node) {
if (node == null)
return "";
return node.text + " " + concat(node.next);
}
public static void main(String[] args) {
// build the list
Node head = new Node("hello");
head.add("this").add("is").add("a").add("linked").add("list");
// print the result of concat
System.out.println(concat(head));
}
}

If your node is null, return an empty string.
Otherwise, get the string, make a recursive call (to get the concatenated result for the rest of the nodes), and append that to the string and return the result.

since this sounds like homework, i'll make a suggestion.
start by writing the method that will work if the list only has one element (ie there is no next node). use that as the basis for your recursive call.

Recursive traversal of a linked list generally looks like seeing if you're at the end of the list (the reference you got was null), and if you're not, doing something to a recursive call upon the next element of the list, and if you are, doing the base case thing. Assuming that nodes look like this from the outside:
public class Node{
public Node getNext();
public String toString();
}
...your method looks like this (inside the class you're using to run this out of):
public String concatList(Node head){
if(head == null){
return ""; //empty list is a null pointer: return empty string
}
return head.toString() + concatList(head.getNext());
}
The end of the list, or no list at all, looks the same- a null pointer- and returns the blank string, as specified; everything else takes the current node and concatenates it to the list created by getting the concatenated version of the entire remainder of the string.
Be careful: if something's corrupted your list so it's actually a loop, this has no checks for that and will run forever until it runs out of stack memory, unless Java correctly detects the loop optimization of this recursive function and it will simply run forever.

Here is a very complete example:
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class RecurisveLinkedListExample
{
public static String concat(final Node node)
{
if (node == null)
{
return "";
}
else
{
return node.getData() + concat(node.getNext());
}
}
public static void main(String[] args)
{
final List<String> input = Arrays.asList("A", "B", "C", "D");
final Node head = new Node(null, input.get(0));
Node previous = head;
for (int i = 1; i < input.size(); i++)
{
previous = previous.addNext(input.get(i));
}
System.out.println(concat(head));
}
public static class Node
{
private final UUID id;
private final Node previous;
private final String data;
private Node next;
public Node(final Node previous, final String data)
{
this.previous = previous;
this.data = data;
this.next = null;
this.id = UUID.randomUUID();
}
public Node getPrevious()
{
return previous;
}
public String getData()
{
return data;
}
public Node addNext(final String data)
{
this.next = new Node(this, data);
return this.next;
}
public Node getNext()
{
return next;
}
#Override
public String toString()
{
return String.format("%s:%s:%s",
this.previous == null ? "HEAD" : this.previous.id,
this.data,
this.next == null ? "TAIL" : this.next.id);
}
}
}

Related

Representing each digit of long number as a node of list

I`m implementing a list class of Big numbers (dynamic list) and trying to represent a received long number as a list
for example : 98765432123
will appear as : 9-8-7-6-5-4-3-2-1-2-3 each digit is a node.
list.
using another class with simple methods (IntNode class):
private int _value;
private IntNode node;
public IntNode(int val) {
_value = val;
node = null;
}
public IntNode(int val, IntNode next) {
_value = val;
node = next;
}
public int get_value() {
return _value;
}
public void set_next(IntNode _next) {
this.node = _next;
}
public void set_value(int _value) {
this._value = _value;
}
public IntNode get_next() {
return node;
}
BigDecimal class attributes :
private IntNode _head
Im using a constructor to receive a long num and represent it as a list by adding each digit to a node.
but having a NullPointerException when trying to add new digit to next node because next node is null.
any help of how to do it without using arrayslist hashmaps etc.. would be appreciated!!
here`s my code where i get nullPointerException error by adding each digit to seperate node.:
public BigDecimalNum(long num) {
_head=new IntNode((int)num%10); // set node to first digit
while(num>0) {
_head.get_next().set_value((int)num % 10); // set next node to next digit.
num/=10;
}
A simple way would be using a string representation of the number:
long num = 98765432123L;
String numStr= String.valueOf(num);
System.out.println(numStr);
String[] arr = numStr.split("");
String lst = String.join("-",arr);
System.out.print(lst);
which gives the ouput:
98765432123
9-8-7-6-5-4-3-2-1-2-3
I modified your IntNode class to simplify the example.
BigDecimalNum bd = new BigDecimalNum(12345l);
System.out.println(bd);
Prints
1-2-3-4-5
the BigDecimalNum constructor basically iterates over the long value and adds the digit to the linked list.
Since you want the head to point to the high order digit, the linked list is constructed backwards, with the head changing each time.
It is then corrected by repositioning to the first valid node.
class BigDecimalNum {
IntNode _head = new IntNode();
public BigDecimalNum(long num) {
while(num > 0) {
_head = _head.addNode((int)(num % 10));
num/=10;
}
_head = _head.next;
}
class IntNode {
private int _value;
private IntNode next;
public IntNode() {
}
adds a new value and returns the next node after adjusting the
new node to set next to the previous one.
public IntNode addNode(int val) {
_value = val;
IntNode t = new IntNode();
t.next = this;
return t;
}
}
I also added a toString method to the BigDecimalNum class to display the linked list. Since you only have a single BigDecimalNum constructor that must take a long it was not necessary to check if the head was null.
public String toString() {
StringBuilder sb = new StringBuilder().append(_head._value);
IntNode start = _head.next;
while(start != null) {
sb.append("-").append(start._value);
start = start.next;
}
return sb.toString();
}
}
Maybe you can construct a new object of IntNode and use the set_next() method. You should also update the "_head" in each loop. Otherwise you would always update the second entry in the list. I came up with this code:
public static IntNode BigDecimalNum(long num) {
IntNode _head = new IntNode((int)num%10); // set node to first digit
num/=10; // go to second digit
IntNode digit = _head;
while (num>0) {
IntNode nextDigit = new IntNode((int)num % 10);
digit.set_next(nextDigit); // set next node to next digit.
num/=10;
digit = nextDigit;
}
return _head;
}

remove function in my linked list not working

I am supposed to build a method that will remove the first instance of a given value in a singly-linked list. However, whenever I try to test this method it will get stuck and I have to force the code to terminate.
edit: following advice, I have made a modified version method Contains that now works well and eliminates pointless repetition of Contains. so happily now the code works as it should!
Here is my code for the method:
public boolean remove(Anything m) {
//INCOMPLETE
if (this.first==null) {
System.out.println("there are no values in the list");
return false;
}
boolean returnValue;
returnValue=false;
if (this.contains(m)==true) {
Node temp=first;
while(temp.next!=null) {
if (temp.next.data==m) {
temp=temp.next.next;
temp.next=null;
returnValue=true;
}
else
returnValue=false;
}
}
return returnValue;
}
Here is my code for testing the method:
list13.addFirst("node5"); list13.addFirst("node4"); list13.addFirst("node3"); list13.addFirst("node2"); list13.addFirst("node1");
System.out.println("5-element list: " + list13);
System.out.println("Testing remove...");
System.out.println(list13.remove("node3"));
and just in case, here is the prebuilt code my assignment came with, if needed:
public class CS2LinkedList<Anything>
{
// the Node class is a private inner class used (only) by the LinkedList class
private class Node
{
private Anything data;
private Node next;
public Node(Anything a, Node n)
{
data = a;
next = n;
}
}
private Node first;
private Node last;
public CS2LinkedList()
{
first = null;
}
public boolean isEmpty()
{
return (first == null);
}
public void addFirst(Anything d)
{
Node temp = first;
first = new Node(d,temp);
}
public void clear()
{
first = null;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.data)) {
return true;
}
}
return false;
}
public String toString()
{
StringBuilder result = new StringBuilder(); //String result = "";
for (Node curr = first; curr != null; curr = curr.next)
result.append(curr.data + "->"); //result = result + curr.data + "->";
result.append("[null]");
return result.toString(); //return result + "[null]";
}
```
Some issues:
At a match, you are reassigning to temp the node that follows after the node to be deleted, and then you clear temp.next. That is breaking the list after the node to be deleted.
The while loop does not change the value of temp when the if condition is not true. So the loop can hang.
You can stop the search when you have identified the node to delete. By consequence you don't need the else inside the while loop.
while(temp.next!=null) {
if (temp.next.data==m) {
// skip the node by modifying `temp.next`:
temp.next = temp.next.next;
returnValue=true;
break; // we removed the targeted node, so get out
}
temp = temp.next; // must move to next node in the list
}
It is a pity that you first iterate the list with this.contains(m), only to iterate it again to find the same node again. I would just remove that if line, and execute the loop that follows any way: it will detect whether the list contains the value or not.
Be aware that your function has no provision for removing the first node of the list. It starts comparing after the first node. You may want to cover this boundary case.

We are trying to find the minimum of a linked list

We are practicing for an exam and are trying to find the minimum value of a linked list in java. This algorithm keeps returning the last element of the list instead of the minimum.
public class minMax {
element head;
public void MinMax(){
this.head = null;
}
public void addElement(element el){
element reference = this.head;
this.head = el;
element nxt = this.head.getNext();
nxt= reference;
}
public int findMin(){
int min = this.head.getValue();
element current = this.head;
while (current != null) {
if(current.getValue() < min){
System.out.println("found min");
min = current.getValue();
}
current = current.getNext();
}
return min;
}
public static void main(String[] args) {
element a = new element(5,null);
element b = new element(55, null);
element c = new element(45, null);
minMax list= new minMax();
list.addElement(a);
list.addElement(b);
list.addElement(c);
int min = list.findMin();
System.out.println(min);
}
}
The main problem is with this part:
element nxt = this.head.getNext();
nxt= reference;
This doesn't change the value of next inside head in the way that you're expecting. It just makes the nxt variable refer to reference.
You haven't included the code for your Element class, but you probably want to update next directly e.g.
this.head.setNext(reference);
Also this line:
public void MinMax() {
is not defining a constructor for your class, as you're probably expecting it to because the case of the name MinMax is different to the name of the class minMax. A constructor also doesn't have a return type so to fix this rename your class MinMax (to follow Java naming conventions) and then remove the void from the constructor definition.
Based on your demo, I just tested it locally and make some modifications.
Using Comparable to enable you to replace the type easily as long as the type implemented the Comparable interface (to find the minimum, you have to compare);
Using head as the sentry to make the adding and deleting (if you need to delete) easier;
By the way, in java you'd better use Uppercase prefix for the class name, so your class name element should be replace by Element. And actually you are encapsulating your class in a good way as a beginner.
Here is the code:
public class HelloWorld {
Node head; // not store any value, just used to link the nodes;
public Comparable findMin() {
if (head == null || head.next == null) {
return null;
}
Comparable min = head.next.value;
Node p = head.next.next;
while(p != null) {
if (min.compareTo(p.value) > 0) min = p.value;
p = p.next;
}
return min;
}
public void add(Node node) {
if (head == null) {
head = new Node(null, node);
} else {
node.next = head.next;
head.next = node;
}
}
public static void main(String... args) {
HelloWorld list = new HelloWorld();
list.add(new Node(5, null));
list.add(new Node(45, null));
list.add(new Node(55, null));
System.out.println(list.findMin().toString());
}
static class Node {
Comparable value;
Node next;
public Node(Comparable theValue, Node theNext) {
this.value = theValue;
this.next = theNext;
}
}
}
The output is working as you expect.
5
Hope it helps you ~

reverse list without deleting the initial list

I'm trying to reverse a list, but l want to keep my initial list. My function reverse doesn't keep the initial list
For example I want to reverse this:
Node n = new Node(1,new Node(12, new Node(34, new Node(3, Node.NIL))));
and my function is:
public Node reverse(){
Node p= this;
if(p == NIL)
return Node.NIL;
if(p.n == Node.NIL)
return p;
Node rest = p.getNext();
p.setNext(Node.NIL);
Node reverseRest = rest.reverse();
rest.setNext(p);
return reverseRest;
}
The length of my old list after the reverse is 1, and I want it to be 4 for this example. My old and my new list have to have the same length after the reverse.
In order to preserve the original list your reverse method must create new Nodes objects, rather than making modifications to existing ones.
If you would like to write a recursive reverse() that takes no parameters, you can do it as follows:
Make a new Node, and copy this node's content into it; set next to NIL
If the next of this node is NIL, return the result of previous step
Otherwise, call reverse() on the next
Take the return value from the previous call, and navigate to its end
Add the new node from step one to the end, and return the result.
A better approach is to change the signature of reverse to take the nodes created so far, in reverse order. This would produce an O(n) algorithm, while the unmodified algorithm above is O(n2).
This is a recursive implementation based on dasblinkenlight's (love the handle!) suggestion: "A better approach is to change the signature of reverse to take the nodes created so far, in reverse order"
public class Node {
private static final Node NIL=null;
public Node(int data, Node next) {
super();
this.data = data;
this.next = next;
}
public int getData() {
return data;
}
public Node getNext() {
return next;
}
private int data;
private Node next;
public String toString()
{
String s = "";
Node cur = this;
while (cur != Node.NIL) {
s += cur.data + ",";
cur = cur.getNext();
}
return s;
}
/* Where the recursive magic happens */
/* build the reversed list in the parameter 'reversed' */
public Node reverse(Node n, Node reversed)
{
if (n == Node.NIL) {
return reversed;
} else {
return reverse(n.next,new Node(n.data,reversed));
}
}
/* Kick off the recursion from the head node */
public Node reverseList() {
return reverse(this,Node.NIL);
}
public static void main (String args[]) {
// Create a sample list
Node n = new Node(1,new Node(12, new Node(34, new Node(3, Node.NIL))));
System.out.println(n);
System.out.println(n.reverseList());
}
}

Order a linked list alphabetically by name

I am having an issue organizing a linked list alphabetically. I am reading the names in from a text file and storing them into a linked list. The problem I am having is how to sort them alphabetically. If anybody could point me in the right direction that would be amazing. The idea is to get the value of the first 3 letters in each name and compare them to the first 3 in the next name. But where would I compare the letters together?
Here is the LinkedListNode class:
public class LinkedListNode
{
private String data;
private LinkedListNode next;
public LinkedListNode(String data)
{
this.data = data;
this.next = null;
}
public String getData()
{
return data;
}
public LinkedListNode getNext()
{
return next;
}
public void setNext(LinkedListNode n)
{
next = n;
}
}
Here is the LinkedList file with the main method:
import java.io.*;
import java.util.Scanner;
public class LinkedList {
public LinkedListNode head;
String fname;
public static void main(String[] args) throws FileNotFoundException{
Scanner scan = new Scanner(new File("Names.txt"));
LinkedList l = new LinkedList();
int i = 1;
while(scan.hasNext()) {
String s = scan.nextLine();
l.insertBack(s);
i++;
}
System.out.print(l.showList());
}
public LinkedList() {
this.head = null;
}
public void insertBack(String data){
if(head == null){
head = new LinkedListNode(data);
}else{
LinkedListNode newNode = new LinkedListNode(data);
LinkedListNode current = head;
while(current.getNext() != null){
current = current.getNext();
}
current.setNext(newNode);
}
}
public String showList(){
int i = 0, j;
String retStr = "List nodes:\n";
LinkedListNode current = head;
while(current != null){
i++;
retStr += "Node " + i + ": " + current.getData() + "\n";
current = current.getNext();
}
return retStr;
}
}
Some pseudo code for you:
OUTER:
for word in file
node = head
while node.next
if word > node.word
node.next
else
Node temp = new Node(word)
temp.next = word.next
node.next = temp
continue OUTER
node.next = new Node(word)
This is an as-you-go insertion sort. After every insert the file will be sorted. Or you could use other sorting algorithms after you read all of the data
if it's if word > node.word this part you're having trouble with, the String#compareTo method will be useful
Try using Collections.sort(list)
Also, for comparing, you can use compareTo function under Comparable Interface
To do easy comparisons, your nodes should implement Comparable. The base Java libraries tend to rely upon this for easy sorting.
The Comaprable interface will require you to implement compareTo (see below).
public int <LinkedListNode> compareTo(LinkedListNode n){
//Case insensitively compare the first 3 characters of the two nodes
String myHead = data.substring(0,3).toLowerCase();
String comparableHead = n.data.substring(0,3).toLowerCase();
return (myHead.compareTo(comparableHead));
}
If you use a standard List structure like, ArrayList, the Collections.sort(list) will be able to use this method to order your list.
And here's an insertion sort based "insert" function for your runTime, using this comparable.
public void insert(String data){
LinkedListNode newNode = new LinkedListNode(data);
if(head == null){
head = newNode;
}else{
LinkedListNode current = head;
LinkedListNode prev;
//This is missing some key edge cases, but it inserts properly in the general case. You'll have to add to it to handle things like running off the list, or this needing to be inserted before the head.
while(current.getNext() != null){
if(current.compareTo(newNode)<0){
newNode.setNext(current);
prev.setNext(newNode);
break;
}
prev = current;
current = current.getNext();
}
}
}

Categories