Working on creating linked lists for an assignment and one requirement is a method named concat which takes a list parameter and appends it to the end of the current list. It's not necessary for this method to use recursion, but our programs are supposed to use recursion heavily. I'm just wondering if it's even possible to come up with a recursive algorithm for this. Our list classes only have a head node, nothing else, and they're not doubly linked.
My current attempt can only append the first value recursively. I know what it's doing wrong, but I can't come up with a solution. The first method is what's actually called on a list with a list being passed in to "concatenate". I then attempt to find the tail of the list and pass these in to the recursive method. This "wrapper" method is a mandatory requirement for our recursive methods. Here's my attempt, but it's obviously failing since I'm having trouble advancing the node reference "pt" to the next node in the list once all of the calls pop off the stack and then re-entering recursive calls to concat. If this is possible with recursion, can you please give me an idea of how to advance this value down the first list and re-enter the recursive calls or maybe just a better general approach towards this problem? Thanks for your time.
public void concat(MyString list1) {
CharacterNode tail = null, pt = list1.head;
// Find the tail of the list
if (pt == null) {
} else if (pt.getNext() == null) {
tail = pt;
} else {
while (pt.getNext() != null) {
pt = pt.getNext();
}
tail = pt;
}
list1.head = concat(list1.head, tail, list1.head);
}
private static CharacterNode concat(CharacterNode lhead, CharacterNode tail, CharacterNode pt) {
// Pass in smaller list every time
// Head traverses down list till the end
// Add new node with (pt's letter, null link)
if (lhead == null) {
// If head is null, we need to add the node
lhead = new CharacterNode(pt.getCharacter(),null);
} else if (tail.getNext() == lhead) {
// If the head is past tail, stop
} else {
// Call concat on a smaller list
lhead.setNext(concat(lhead.getNext(),tail,pt));
}
return lhead;
}
Here's CharacterNode:
class CharacterNode {
private char letter;
private CharacterNode next;
public CharacterNode(char ch, CharacterNode link) {
letter = ch;
next = link;
}
public void setCharacter(char ch) {
this.letter = ch;
}
public char getCharacter() {
return letter;
}
public void setNext(CharacterNode next) {
this.next = next;
}
public CharacterNode getNext() {
return next;
}
}
MyString:
class MyString {
// member variable pointing to the head of the linked list
private CharacterNode head;
// default constructor
public MyString() {
}
// copy constructor
public MyString(MyString l) {
}
// constructor from a String
public MyString(String s) {
}
// for output purposes -- override Object version
// no spaces between the characters, no line feeds/returns
public String toString() {
}
// create a new node and add it to the head of the list
public void addHead(char ch) {
}
// create a new node and add it to the tail of the list -- "wrapper"
public void addTail(char ch) {
}
// Recursive method for addTail
private static CharacterNode addTail(CharacterNode L, char letter) {
}
// modify the list so it is reversed
public void reverse() {
}
// remove all occurrences of the character from the list -- "wrapper"
public void removeChar(char ch) {
}
// Recursive removeChar method
private static CharacterNode removeChar(CharacterNode n, char letter) {
}
// "wrapper" for recursive length()
public int length() {
}
// Returns the length of the linked list
private static int length(CharacterNode L) {
}
// concatenate a copy of list1 to the end of the list
public void concat(MyString list1) {
}
// recursive method for concat
private static CharacterNode concat(CharacterNode lhead, CharacterNode tail, CharacterNode pt) {
}
}
To concatenate two linked lists, you have to make the last node of first list to point to first node of the second list.
Node first_list = ... // head node
Node second_list = ... // head node
...
Node last_node = first_list.getLastNode()
last_node.setNext(second_list)
Now concentrate on implementing getLastNode(). It can be done very simply by using either recursion or iteration, literally in 2 lines.
Related
I have a list and want to try to use a search method. It works for values 3 digits or shorter, but will not work for longer numbers. Where am I going wrong?
class ListNode<T> {
T data; // data for this node
ListNode<T> nextNode; // reference to the next node in the list
// constructor creates a ListNode that refers to object
ListNode(T object) {this(object, null);}
// constructor creates ListNode that refers to the specified
// object and to the next ListNode
ListNode(T object, ListNode<T> node) {
data = object;
nextNode = node;
}
T getData() {return data;}
ListNode<T> getNext() {return nextNode;}
}
// class List definition
public class List<T> {
public ListNode<T> firstNode;
private ListNode<T> lastNode;
private String name; // string like "list" used in printing
// constructor creates empty List with "list" as the name
public List() {this("list");}
// constructor creates an empty List with a name
public List(String listName) {
name = listName;
firstNode = lastNode = null;
}
// insert item at end of List
public void insertAtBack(T insertItem) {
if (isEmpty()) { // firstNode and lastNode refer to same object
firstNode = lastNode = new ListNode<T>(insertItem);
}
else { // lastNode's nextNode refers to new node
lastNode = lastNode.nextNode = new ListNode<T>(insertItem);
}
}
public boolean search(ListNode <T> node,T data)
{
if (node == null){
System.out.println("Not found");
return false;}
if (node.data == data){
System.out.println("Found");
return true;}
return search(node.nextNode,data);
}
}
Main class:
import java.util.Scanner;
public class ListTest {
public static void main(String[] args) {
List <Integer> list=new List<>();
// insert integers in list
list.insertAtBack(11);//is found
list.insertAtBack(10);
list.insertAtBack(111);
list.insertAtBack(1234); //value that is not being found
list.insertAtBack(123);
//prep scanner
Scanner input = new Scanner(System.in);
System.out.print("Please enter a value:");
int searchInt = input.nextInt();
//search
list.search(list.firstNode,searchInt);
}
}
As shown, it works with 10,11, and 123, but not 1234. Any help or direction is appreciated. I think it could be due to not having enough nodes, but I am not sure.
Your problem is in how you are testing for a match between the search term and each value in the list. To test if the integer value of two Integer objects are the same, you have to use Integer.equals() rather than ==.
Change this line of your code:
if (node.data. == data) {
to:
if (node.data.equals(data)) {
and you'll get the result that you expect. The reason that == doesn't work is that it is testing if the two values are the exact same object. This generally won't be the case for two Integer objects that contain the same primitive integer value.
The reason that your code seems to work for many of your test values is that Java caches the first N Integer objects (I don't know what N is) for memory efficiency figuring that these values are very commonly used. So when you create a new Integer object with a small integer value, Java returns the same exact object that represents that value every time you seem to be creating a new object. So it isn't that you're adding more than 3 items to your list. It's that one of your values is larger than the largest value Integer object that Java caches.
UPDATE: I googled and found that Java caches Integer objects with values in the range –128 to +127.
I'm trying to used recursive method to complete the addLast method in a singly linked list, however, the code gives me a wrong output of list.size() = 2 and list.getFirst() = 5. The reason should be due to the line
SLList p=this;
It seems changing p reference changes "this" reference as well, which is not so logic to me. Could anyone give some details about this? Thx
public class SLList {
public class IntNode {
public int item;
public IntNode next;
public IntNode(int i, IntNode n) {
item = i;
next = n;
}
}
private IntNode first;
public SLList(int x) {
first = new IntNode(x, null);
}
/** Adds an item to the front of the list. */
public void addFirst(int x) {
first = new IntNode(x, first);
}
/** Retrieves the front item from the list. */
public int getFirst() {
return first.item;
}
/** Adds an item to the end of the list. */
public void addLast(int x) {
SLList p = this;
if (p.first. next == null) {
p.first.next = new IntNode (x, null);
}
else {
p.first = p.first.next;
p.addLast(x);
}
}
/** Returns the number of items in the list using recursion. */
public int size() {
/* Your Code Here! */
SLList p = this;
if (p.first == null) {
return 0;
}
else if (p.first.next == null){
return 1;
}
else {
p.first = p.first.next;
return 1 + p.size();
}
}
public static void main (String[] args) {
SLList list=new SLList (5);
list.addFirst(10);
list.addFirst(15);
list.addLast(17);
System.out.println(list.getFirst());
System.out.println(list.size());
}
}
The problem is nothing to do with the assignment of this. Nothing can change this. Period.
(But things can change the state of the object that this refers to.)
The real problem is in your implementation of the size method. Your size method is causing the list to change. It shouldn't. In your case, the change causes:
the size() method to return the wrong value
subsequent getFirst() calls to return the wrong value.
I won't say exactly where the bug, but you should be able to spot it yourself by a process of elimination. (Or if that fails, use a debugger and try to observe where the list is changing.)
There are bigger problems with your algorithms than you think. size() is incorrect. You can fix this if you realize that you need to count the number of IntNode objects in the list. Similarly all other methods need to manipulate IntNode objects.
SLList p = this;
p reference to the same SLList object. if you make any changes to 'p' then it will also happened to 'this', becuase of reference type (not value type).
Here in the statement
p.first = p.first.next;
the reference to the first is changed when you call 'addLast' method. You loss the reference to the first item.
If you remove the line
list.addLast(17);
in main method you will see the correct answer. The problem is with this method.
Change the method as follow and add the new method below.
/** Adds an item to the end of the list. */
public void addLast(int x) {
addLast(x, this.first);
}
private void addLast(int x, IntNode node){
if(node.next == null){
node.next = new IntNode (x, null);
}else {
node = node.next;
addLast(x, node);
}
}
Then you will not lose the reference to first item and now it works fine,
Problem in your implementation is addLast and size method are changing the value of field variable first.
It don't matter whether you assignthis to some variable or use directly.
Because assigning this to some variable does not create new this object but assign's reference to that variable.
So you should first copy value of first field variable to some local variable then iterate on it.In this way your first will not change.
Hint: Don't change the first variable reference.
Your addLast() and size() changes value of first which is wrong.
Problem is in this line.
p.first = p.first.next;
I saw some solutions, but I am still unable to resolve the error in my code. My deleteFromStart method is not removing any elements from the list. Both invocations of ob.display() produce the same output. Can you tell me what I am missing, or where the error is?
LikedList:
package lab5;
public class LinkedList {
public static void main(String argsp[]){
List ob = new List();
ob.addAtStart("y", 6);
ob.addAtStart("w", 4);
ob.addAtStart("z", 3);
ob.addAtEnd("a",3);
ob.addAtEnd("b",4);
ob.addAtEnd("c",5);
ob.display();
ob.deleteFromStart();
System.out.println("\n");
ob.display();
}
}
List:
package lab5;
public class List {
Node head;
public List(){
head=null;
}
public List(Node e){
head=e;
}
Node oldfirst=null;
Node lasthead=null;
public void addAtStart(String name, int age){
Node newObject= new Node(name,age);
newObject.next=head;
if (oldfirst==null) {
oldfirst = newObject;
}
head = newObject;
lasthead = head;
}
public void display() {
Node store = head;
while (store != null) {
store.display();
store=store.next;
System.out.println();
}
}
public void addAtEnd(String name, int age){
Node atEndValue = new Node(name, age);
oldfirst.next = atEndValue;
oldfirst = atEndValue;
}
public void deleteFromStart() {
while (lasthead != null) {
lasthead = lasthead.next;
}
}
public boolean isEmpty() {
return head == null;
}
Node:
package lab5;
public class Node {
String name;
int age;
Node next;
public Node(){
name="Abc";
age=10;
next=null;
}
public Node(String name, int age ){
this.name=name;
this.age=age;
next = null;
}
public void display(){
System.out.println("Name: " + name + " Age: " + age);
}
}
tl;dr To remove the first element in a linked-list:
head = head.next
When you're implementing a singly-linked list, you really only need to keep a single pointer: head (i.e. a reference to the first node in the list. In practice, it's also useful to keep track of the last element in the list (commonly referred to as tail). This allows constant-time operations at the end of the list, which are useful if you're frequently adding elements at the end. So, with this basic implementation, you end up with something like this:
class LinkedList {
private Node head = null;
private Node tail = null;
public LinkedList() {}
public LinkedList(Node e) {
head = e;
tail = e;
}
}
class Node {
Node next = null;
// other data
}
Adding and removing elements in a linked list boils to down to updating what the head and tail variables are referring to. Consider a singly-linked list with three elements, [A, B, C]. The values head and tail values align like this:
A -> B -> C -> null
^ ^
| |
head tail
If you want to insert a new element, X, there are two steps:
1) Tell X.next to refer to A:
X -> A -> B -> C -> null
^ ^
| |
head tail
2) Update head to refer to X:
X -> A -> B -> C -> null
^ ^
| |
head tail
You move head and tail around in similar fashion, depending on whether you're adding or removing, and whether or not the operation is at the beginning or end of the list.
Removing an element from the start (assuming that the list is not empty) is as simple as updating head to refer to the next element. In our example above, this would mean moving head to refer to X.next, which is A:
X -> A -> B -> C -> null
^ ^
| |
head tail
Now remember, the linked list is only directly aware of head and tail, so once you update head to refer to A there is nothing referencing X anywhere in your application, and it has effectively been deleted (in Java this will cause it to be garbage-collected).
Effectively what we did above was simply head = head.next. Again, you'll have to ensure the list isn't empty first, since head.next will cause a null pointer exception if the list is empty.
I'd also suggest removing oldfirst and lasthead, and updating your add* methods based on the theory above.
This actually is not a Linked List it is more of a Queue where you have rear and front pointers.
While displaying the items in the list you are using the "head" pointer where as while deleting from start you are using "lasthead". This would move the lasthead but wont assign the value to head again.
public void deleteFromStart(){
while(lasthead!=null){
this.lasthead=lasthead.next;
}
head = this.lasthead;
}
Well i tried this code and it delete's all the elements from the start (I hope this is what you wanted)
For deleting first element:
public void deleteElementAtStart()
{
if(lasthead != null)
{
this.lasthead = lasthead.next;
}
else
{
System.out.println("List is already empty!");
}
head = lasthead;
}
Editted it.
Thank you everyone! I realize my mistakes I am using extra objects that's why during solution I got these two method.
public void deleteFromStart(){
while(lasthead.next!=null){
lasthead=lasthead.next;
head=lasthead;
break;
}
}
or
public void deleteFromStart(){
while(head.next!=null){
head=head.next;
break;
}
}
I have been making an implementation of a Linked List to manipulate it to do various things so I could better learn it and I have come across something which I don't understand.
I have made three classes: Node, LinkedListExample, LinkedListTest
My node class looks like:
public class Node {
Node next;
Object data;
// Node constructor
public Node(Object dataValue) {
next = null;
data = dataValue;
}
public Object getData() {
return data;
}
public void setData(Object dataValue) {
data = dataValue;
}
public Node getNext() {
return next;
}
public void setNext(Node nextValue) {
next = nextValue;
}
}
My Linked List looks like:
public class LinkedListExample {
private Node head;
private int listCount;
public LinkedListExample() {
head = new Node(null);
listCount = 0;
}
public void add(Object data) {
Node temp = new Node(data);
Node current = head;
while (current.getNext() != null) {
current = current.getNext();
}
current.setNext(temp);
}
public int size() {
for (Node n = head; n.next != null; n = n.next) {
listCount++;
}
return listCount;
}
public String toString() {
String result = "";
Node current = head;
while (current.getNext() != null) {
current = current.getNext();
result += current.getData() + " ";
}
return result;
}
public String headString() {
String result = "";
Node current = head;
//current = current.getNext();
result = current.getData() + ""; /* Returns null currently */
/* If previous line replaced by result = current.getData().toString() it would result in NULL POINTER EXCEPTION */
return result;
}
}
Finally, my Linked List Test class looks like:
public class LinkedListTest {
public static void main(String[] args) {
LinkedListExample example = new LinkedListExample();
example.add(1);
example.add(2);
example.add(3);
System.out.println("The list looks like: " + example.toString());
System.out.println("The size is: " + example.size());
System.out.println("The list head is: " + example.headString());
}
}
My question is in my constructor, I create a Node object, head, and set it to null. I later go on to add three objects, 1 2 and 3 to my Linked List. I am now confused as to what is in my Linked List? Is the null value included or not? Why or why not?
When I run the program as is, my print statement would say The list looks like 1 2 3. But if I was to flip the lines within the while loop in my toString() method in LinkedListExample to look like:
current = current.getNext();
result += current.getData() + " ";
Then the output would be The list looks like null 1 2.
Does null never get replaced?
The same goes for headString(). It currently outputs The list head is: null but if I were to uncomment the previous line, I would get The list head is: 1.
On a side note, what is also the difference between using "" and toString() because as commented out in the code above, in one situation it prints out null while the other throws a null pointer exception?
Sorry if these questions are simple, I just am lost on this concept.
This is one particular way of implementing a linked list. The "head" node is not counted as part of the list.
If you counted the head node as part of the list, then when you add an item, you will find that you need to add it differently depending on whether it's the first node or not. Removing also works differently depending on whether the node is the first node.
To simplify the code, you can create a "header node" that is not used to store a value. If you do this, then you don't need to think about how to insert or remove nodes at the start of the list. Nodes with data are always after the head node, so they're never at the start.
you create a new Node and set the data value to null. So in your c'tor you create a new Node with next=null and data=dataValue=null.
So your LinkedListExample head is an element:
Node: next=null, data=null
Your add()-method creates a temporary node and sets a (temporary) current node.
Temp: next=null, data=1
Current=head: next=null, data=null
As current has no next you replace it:
Head: next=1, data=null
Next: next=null, data=1
And so on.
You head stays the same, but output null wont have an effect, it's just empty.
So, your null-head never get's replaced and the change in output is because of your
while (current.getNext() != null) {
Pretty easy question:
Recursively how can I create an array of a binary search tree (in order) which uses this constructor:
public class OrderedSet<E extends Comparable<E>> {
private class TreeNode {
private E data;
private TreeNode left, right;
public TreeNode(E el) {
data = el;
left = null;
right = null;
}
}
private TreeNode root;
public int size = 0;
public OrderedSet() {
root = null;
}
In-Order means you first have to traverse the left part of the tree, so:
TreeNode tree // this is your tree you want to traverse
E[] array = new E[tree.size]; // the arrays length must be equivalent to the number of Nodes in the tree
int index = 0; // when adding something to the array we need an index
inOrder(tree, array, index); // thats the call for the method you'll create
The method itself could looks something like this:
public void inOrder(TreeNode node, E[] array, int index){
if(node == null){ // recursion anchor: when the node is null an empty leaf was reached (doesn't matter if it is left or right, just end the method call
return;
}
inOrder(node.getLeft(), array, index); // first do every left child tree
array[index++]= node.getData(); // then write the data in the array
inOrder(node.getRight(), array, index); // do the same with the right child
}
Somewhat like that. I am just not sure about the index and where it needs to be incremented. If you don't want to worry about the index or if you don't know how many nodes are in the tree, then use an ArrayList instead and transform it in the end to an array.
Normally a cleaner call method is build around the recursive method like this:
public E[] inOrderSort(TreeNode tree){
E[] array = new E[tree.size];
inOrder(tree, array, 0);
return array;
}
Thanks, that worked great. Java wouldn't allow me to make an array of generics so using your algorithm I made it work with an ArrayList (like you suggested) Here's the method (using the above constructor) just incase someone else asks the same question. (Ref is my reference to the current tree node)
public ArrayList<E> toArray() {
ArrayList<E> result = new ArrayList<E>();
toArrayHelp(root, result);
return result;
}
private void toArrayHelp(TreeNode ref, ArrayList<E> result) {
if (ref == null) {
return;
}
toArrayHelp(ref.left, result);
result.add(ref.data);
toArrayHelp(ref.right, result);
}