I created my own linked list in java(code below) and I was trying to store DNA?RNA sequences from a text file in an array of a custom data type that contains the enum DNA/RNA, as well as a linked list containing the actual DNA sequence. I don't know if the characters are just not being inserted into the linked list or if there is a problem with my toString but the output only prints the position and enum type, not the sequence from the list. Code is below
My node class
public class Node<E> {
private Node<E> next;
protected E data;
Node(E data,Node<E> nextVal){
this.data=data;
next=nextVal;
}
Node(Node<E> nextVal){
next=nextVal;
}
Node<E> Next(){
return next;
}
Node<E>setNext(Node<E> nextVal){
return next=nextVal;
}
E data(){
return data;
}
E setData(E it){
return data=it;
}
}
My Linked List Class
public class MyLinkedList<E> implements List<E>{
private Node<E> head;
private Node<E> tail;
protected Node<E> curr;
private int size;
MyLinkedList(int size){
this();
}
MyLinkedList(){
curr=tail=head=new Node<E>(null);
size=0;
}
#Override
public void clear() {
head.setNext(null);
curr=tail=head=new Node<E>(null);
size=0;
}
#Override
public void insert(E item) {
curr.setNext(new Node<E>(item, curr.Next()));
if(tail==curr)
tail=curr.Next();
size++;
}
#Override
public void append(E item) {
tail=tail.setNext(new Node<E>(item, null));
size++;
}
#Override
public E remove() {
if(curr.Next() ==null)
return null;
E item=curr.Next().data();
if(tail==curr.Next())
tail=curr;
curr.setNext(curr.Next().Next());
size--;
return item;
}
#Override
public void moveToStart() {
curr =head;
}
#Override
public void moveToEnd() {
curr=tail;
}
#Override
public void prev() {
if(curr==head)
return;
Node<E> temp=head;
while (temp.Next()!=curr)
temp=temp.Next();
curr=temp;
}
#Override
public void next() {
if(curr!=tail)
curr=curr.Next();
}
#Override
public int length() {
return size;
}
#Override
public int currPos() {
Node<E>temp=head;
int i;
for(i=0;curr!=temp;i++)
temp.Next();
return i;
}
#Override
public void moveToPos(int pos) {
assert (pos>=0)&& (pos<=size):
"Position out of Range";
curr=head;
for(int i=0;i<pos;i++)
curr.Next();
}
#Override
public E getValue() {
if(curr.Next()==null)
return null;
return curr.Next().data();
}
#Override
public String toString() {
String result = "";
Node current = head;
while(current.Next() != null){
result += current.data();
if(current.Next() != null){
result += ", ";
}
current = current.Next();
}
return "" + result;
}
}
This is the SequenceArr class which handles the operations on the array mentioned above (not complete here but all that is used in this example)
public class SequenceArr {
private TypeSeq [] SeqArr;
private int size=0;
private int MAXSIZE;
public SequenceArr(int MAXSIZE){
this.MAXSIZE=MAXSIZE;
SeqArr =new TypeSeq[MAXSIZE];
size=0;
}
public void insert(int pos, Type t, MyLinkedList<Character> seq){
TypeSeq currentEl=new TypeSeq(t,seq);
assert pos<=MAXSIZE: "Position over maximum size of array";
SeqArr[size]=currentEl;
size++;
}
public void remove(int pos){
if(SeqArr[pos]!=null){
while(SeqArr[pos+1]!=null){
SeqArr[pos]=SeqArr[pos+1];
}
if(SeqArr[pos+1]==null){
SeqArr[pos]=null;
}
}
else
System.out.print("No sequence to remove at specified position");
}
public void print(){
int i=0;
while (SeqArr[i]!=null){
System.out.println(i+"\t"+SeqArr[i].getType()+"\t"+SeqArr[i].getBioSeq().toString());
i++;
}
}
public void print(int pos){
if(SeqArr[pos]==null)
System.out.print("No sequence to print at specified position");
else
System.out.println(SeqArr[pos].getType()+"\t"+SeqArr[pos].getBioSeq().toString());
}
The custom data type i created that the array is made of
public class TypeSeq {
private Type type;
private MyLinkedList<Character> BioSeq;
public TypeSeq(Type type, MyLinkedList<Character> BioSeq){
this.type=type;
this.BioSeq=BioSeq;
}
public MyLinkedList<Character> getBioSeq() {
return BioSeq;
}
public void setBioSeq(MyLinkedList<Character> bioSeq) {
BioSeq = bioSeq;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
}
and my DNAList class which handles input and contains the main method
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class DNAList {
static SequenceArr seqar;
public static void main(String []args){
MyLinkedList<String> hey=new MyLinkedList<>();
hey.append("Hello");
int arraysize= Integer.parseInt(args[0]);
String filePath=args[1];
File file=new File(filePath);
seqar=new SequenceArr(arraysize);
exefromFile(file);
}
public static void exefromFile(File file){
Scanner sc;
try{
sc=new Scanner(file);
while(sc.hasNextLine()){
String cmd=sc.nextLine();
if(!cmd.equals(""))
execute(cmd);
}
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
public static void execute(String s){
s=s.trim();
String [] commands=s.split("\\s+");
switch (commands[0])
{
case "insert":
int pos=Integer.parseInt(commands[1]);
Type t=Type.fromString(commands[2]);
char [] charArr=commands[3].toCharArray();
MyLinkedList<Character> seq=new MyLinkedList<>(charArr.length);
char curChar;
for(int i=0;i<seq.length();i++){
curChar=charArr[i];
if(t==Type.DNA&&(curChar=='A'||curChar=='C'||curChar=='G'||curChar=='T'))
seq.append(charArr[i]);
else
System.out.print("Error occurred while inserting");
}
seqar.insert(pos,t,seq);
break;
case "remove":
pos=Integer.parseInt(commands[1]);
seqar.remove(pos);
break;
case "print":
if(commands.length>1&&commands[1]!=null){
pos=Integer.parseInt(commands[1]);
seqar.print(pos);
}
else
seqar.print();
break;
case "clip":
pos=Integer.parseInt(commands[1]);
int start =Integer.parseInt(commands[2]);
int end =Integer.parseInt(commands[3]);
seqar.clip(pos,start,end);
break;
case "copy":
int pos1=Integer.parseInt(commands[1]);
int pos2=Integer.parseInt(commands[2]);
seqar.copy(pos1,pos2);
break;
case "transcribe":
pos=Integer.parseInt(commands[1]);
seqar.transcribe(pos);
break;
}
}
}
The input .txt file will say something like
insert 0 DNA AATTCCGGAATTCCGG
print
but the output will just be
0 DNA
and the sequence will not be printed. Any ideas?
There are quite a lot of bugs in the code, to mention some:
MyLinkedList(int size){
this();
}
MyLinkedList(){
curr=tail=head=new Node<E>(null);
size=0;
}
this always initialises your list with size 0.
char [] charArr=commands[3].toCharArray();
MyLinkedList<Character> seq=new MyLinkedList<>
(charArr.length);
I don't get the point of initialising your list with the size of 4 every-time. Also note, it's not going to initialise with the given size as you are always overriding it with 0.
#Override
public void insert(E item) {
curr.setNext(new Node<E>(item, curr.Next()));
if(tail==curr)
tail=curr.Next();
size++;
}
You are not utilising the concept of head at all, your first insert is a special case and needs to handled wisely.
#Override
public String toString() {
String result = "";
Node current = head;
while(current.Next() != null){
result += current.data();
if(current.Next() != null){
result += ", ";
}
current = current.Next();
}
return "" + result;
}
head is always going to be null, when you print it's always going to result in first element being null. Moreover, when you find a node with it's next pointing to null, you should use its data. In your code, before returning the result you need to append the data from the last element too.
Related
Here is a link-based Stack class.
import java.util.Iterator;
public class LStack<T>
{
private Link top;
private int size;
public LStack()
{
top = null;
size = 0;
}
#Override
public String toString()
{
StringBuffer sb = new StringBuffer();
sb.append("[");
for(Link nav = top; nav != null; nav=nav.getNext())
{
sb.append(nav.getDatum());
if(nav.getNext() != null)
{
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
public void push(T newItem)
{
top = new Link(newItem, top);
size++;
}
public T pop()
{
if(isEmpty())
{
throw new EmptyStackException();
}
size--;
T out = top.getDatum();
top = top.getNext();
return out;
}
public T peek()
{
if(isEmpty())
{
throw new EmptyStackException();
}
return top.getDatum();
}
public void clear()
{
top = null;
size = 0;
}
public int size()
{
return size;
}
public boolean isEmpty()
{
return top == null;
}
public Iterator<T> iterator()
{
return new LStackIterator();
}
/********************aliens*******************/
class LStackIterator implements Iterator<T>
{
private Link current;
public LStackIterator()
{
current = top;
}
public T next()
{
T out = current.getDatum();
current = current.getNext();
return out;
}
public boolean hasNext()
{
return current.getNext() != null;
}
}
public static void main(String[] args)
{
LStack<String> elStack = new LStack<>();
elStack.push("A");
elStack.push("B");
elStack.push("C");
elStack.push("D");
for(String quack: elStack)
{
System.out.println(quack);
}
System.out.printf("The size is %d\n", elStack.size());
System.out.println(elStack);
System.out.println(elStack.pop());
System.out.println(elStack.pop());
System.out.println(elStack.pop());
System.out.println(elStack.pop());
System.out.println(elStack);
}
class Link
{
private T datum;
private Link next;
public Link(T datum, Link next)
{
this.datum = datum;
this.next = next;
}
public Link(T datum)
{
this(datum, null);
}
public T getDatum()
{
return datum;
}
public Link getNext()
{
return next;
}
}
}
I then try to run and get this.
$ javac LStack.java
LStack.java:95: error: incompatible types: Object cannot be converted to String
for(String quack: elStack)
^
1 error
What is happening here? Changing the type from String to Object causes it to work, but I am not using any raw types.
You must implement Iterable for "For-Each" loop
public class LStack<T> implements Iterable<T>
Hi,
Update: Thanks for all your suggestion
assuming that, this exercise it's like a rebus,
I have a list of numbers made with the concept of Cons and Nil,
List l = new Cons(**3**, new Cons(**2**,new Cons(**1**, new
Cons(**4**, new Cons(**1**, new Nil())))));
and I want to count how many of them are immediately followed by a lower number, recursively.
For example
[5,0,5,3].count() == 2, [5,5,0].count() == 1
The count() method is made by me (it cannot have any parameters), the rest is default, and I can't make and other method or use already defined one's like add(),size()...
The "NEXT" must have the next value after the current elem but I can't get a solution.
Any solutions are welcome.
abstract class List {
public abstract boolean empty();
public abstract int first();
public abstract int count();
}
class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty(){
return false;
}
public int first(){
return elem;
}
#Override
public int count() {
if(elem>NEXT) {
return 1 + next.count();
}else {
return next.count();
}
}
```![enter image description here](https://i.stack.imgur.com/kWo0v.jpg)
The following code will create a recursive list with N elements with N value being defined by the size of the amount of elements found in the int array called elements in RecursiveList class. Call the startRecursion() method to create a recursive list with the defined elements and call count() to get the amount of elements in the array that are immediately followed by a lower number.
Main Class
This your application entry point:
public static void main(String[] args) {
int count = RecursiveList.startRecursion().count();
System.out.printf("List has %d recursive elements", count);
}
RecursiveList Class
abstract class RecursiveList {
protected static int index = -1;
protected static int[] elements = new int[]{ 5,2,1,4,3,2,6 };
public static RecursiveList startRecursion() {
return new Cons();
}
public abstract boolean empty();
public abstract int count();
public abstract Integer getElement();
public static int incIndex() {
return index += 1;
}
}
Cons Class
public class Cons extends RecursiveList {
private static int result;
private final Integer elem;
private final RecursiveList prev;
private final RecursiveList next;
private Cons(Cons parent) {
prev = parent;
elem = incIndex() < elements.length ? elements[index] : null;
System.out.printf("Creating new Cons with element %d(%d)%n", elem, index);
next = elem != null ? new Cons(this) : null;
}
Cons() {
this(null);
}
public boolean empty() {
return false;
}
#Override
public /*#Nullable*/ Integer getElement() {
return elem;
}
#Override
public int count() {
if (elem != null)
{
if (prev != null && elem < prev.getElement())
result += 1;
if (next != null) {
return next.count();
}
}
return result;
}
}
EDIT
Alright here is the answer you were actually looking for. This completely conforms to the limitations imposed on this exercise that you provided. The solution uses pure Java, neither the class nor any of it's method or field declarations were modified in any way and no such new elements were added. I've only added the implementation where the exercise said you should.
Main Class
public static void main(String[] args) {
List l = new Cons(3, new Cons(2,new Cons(1, new
Cons(4, new Cons(1, new Nil())))));
assert l.count() == 3;
l = new Cons(5, new Nil());
assert l.count() == 0;
l = new Cons(5, new Cons(5, new Cons(0, new Nil())));
assert l.count() == 1;
l = new Cons(5, new Cons(0, new Cons(5, new Cons(3, new Nil()))));
assert l.count() == 2;
System.out.println("All tests completed successfully!");
}
Cons Class
import java.util.NoSuchElementException;
public class Cons extends List {
private int elem;
private List next;
public Cons(int elem, List next) {
this.elem = elem;
this.next = next;
}
public boolean empty()
{ return false; }
public int first()
{ return elem; }
public int count()
{
try {
if (first() > next.first()) {
return 1 + next.count();
}
else return next.count();
}
catch (NoSuchElementException e) {
return 0;
}
}
}
Nil Class
import java.util.NoSuchElementException;
public class Nil extends List {
public boolean empty()
{ return true; }
public int first()
{ throw new NoSuchElementException(); }
public int count()
{
throw new IllegalAccessError();
}
}
public int NEXT(){
if(next!=null)
return next.first()
else
throw new Exception("No next element")
}
Here is my class:
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node (){}
public Node (int x)
{
data = x;
}
public int data()
{
return data;
}
public Node next()
{
return next;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
Here is my interface:
public interface Set {
public boolean isEmpty();
public void makeEmpty();
public boolean isMember(int x);
public void add(int x);
public void remove(int y);
public void union(Set other, Set result);
public void intersection (Set other, Set result);
public void difference (Set other, Set result);
#Override
public String toString();
#Override
public boolean equals(Object other);
public void setList(int i); //i added this to use it as an identifier for each
//list element in the set array
public String getListId(); //these two extra methods make life easier
}
I have a method like this (in the LinkedListSet class):
public void difference (Set other, Set result)
{
if (other.isEmpty())
{
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty())
{
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
differenceHelper(this.first, othr.first, res);
result = res;
}// the print statements were added for debugging
The problem is, in the above method I am unable to cast the Set Other into its linked list implementation. When I call this method in the main program, the parameter is actually of type linked list (so I don't get any errors obviously).
However, all the instance variables are null. The list is empty before and after I cast it (when it actually isn't empty). I know this is because the interface doesn't include any information about the Nodes, but is there anything I can do other than editing the interface to incorporate the Node?
I hope I've made this clear enough. Any help would be appreciated.
edit:
In the main program I created an array of Sets.
Set[] sets = new Set[7];
for (int i = 0; i< sets.length; i++) //initialize each element
{
sets[i] = new LinkedListSet();
}
each list has nodes with data values which are added on later on in the code...
then I call the difference method.
sets[0].difference(sets[1], sets[4])
sets[1].isEmpty returns true for some reason (even though it is not).
If I were to do something like:
System.out.println(sets[1].first.data()) I would have no problem whatsoever.
For some reason all the values become null when the parameters are passed to the difference method.
public boolean isEmpty()
{
return first == null;
}
I tested what you are trying to do with the following code and I see no problems:
import org.junit.Test;
public class RandomCastTest {
public interface Set {
boolean isEmpty();
void add(int x);
void difference(Set other, Set result);
#Override
String toString();
#Override
boolean equals(Object other);
}
public class LinkedListSet implements Set {
private class Node //much easier as a private class; don't have to extend
{
private int data;
private Node next;
public Node() {
}
public Node(int x) {
data = x;
}
public int data() {
return data;
}
public Node next() {
return next;
}
public void next(Node node) {
next = node;
}
}
private Node first;
private int Size;
private int whichList; //used to identify the particular LL object
#Override
public boolean isEmpty() {
return first == null;
}
#Override
public void add(int x) {
Node node = new Node(x);
if (first == null) {
first = node;
} else {
Node currentNode;
Node nextNode = first;
do {
currentNode = nextNode;
nextNode = currentNode.next();
} while (nextNode != null);
currentNode.next(node);
}
Size++;
}
#Override
public void difference(Set other, Set result) {
if (other.isEmpty()) {
System.out.println("The set is empty before cast");
}
LinkedListSet othr = (LinkedListSet) other;
LinkedListSet res = (LinkedListSet) result;
if (this.isEmpty() || othr.isEmpty()) {
if (othr.isEmpty())
System.out.println("The set is empty after cast");
if (this.isEmpty())
System.out.println("This is also empty");
return;
}
result = res;
}
}
#Test
public void test() {
Set[] sets = new Set[7];
for (int i = 0; i < sets.length; i++) {
sets[i] = new LinkedListSet();
}
for (int i = 0; i < 5; i++) {
sets[1].add(i);
}
for (int i = 5; i < 10; i++) {
sets[0].add(i);
}
sets[0].difference(sets[1], sets[4]);
// ... find difference
}
}
To simplify I removed unimplemented methods from the interface. Also added the add method implementation. Please see if it works for you.
I wish to implement a Queue based in a simple linked list class, without using java.util.
When I call the addEnd method in List class through enqueue method, I receive a java.lang.NullPointerException, though I expect the second element.
Which solution can I take?
The node class
public class Node {
private int value;
private Node next;
public Node(int val) {
value = val;
}
public Node(int val, Node next) {
value = val;
this.next=next;
}
public Node(Node next) {
this.next=next;
}
public int getValue() {
return value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public void displayNode() {
System.out.print(" "+value+" ");
}
}
My interface
public interface MyQueue {
void enqueue(int oVal);
int dequeue();
}
The List
public class List {
private Node first;
private Node last;
private int counter;
public List() {
first = null;
last = null;
}
public boolean isEmpty() {
return first==null;
}
public void addEnd(int val) {
Node n1 = new Node(val);
if( isEmpty() ) {
first = n1;
} else {
last.setNext(n1);
last = n1;
}
}
public int deleteStart() {
int temp = first.getValue();
if(first.getNext() == null){
last = null;
first = first.getNext();
}
return temp;
}
public void displayList() {
Node current = first;
while(current != null) {
current.displayNode();
current = current.getNext();
}
System.out.println("");
}
public int size() {
return counter;
}
}
The Queue
public class Queue implements MyQueue {
private List listQ;
public Queue() {
listQ = new List();
}
public boolean isEmpty() {
return listQ.isEmpty();
}
public void enqueue(int oVal) {
listQ.addEnd(oVal);
}
public int dequeue() {
return listQ.deleteStart();
}
public void displayQueue() {
System.out.print("Queue ");
listQ.displayQueue();
}
}
public class App {
public static void main(String[] args) {
Queue q1 = new Queue();
System.out.println("Two insertions");
q1.enqueue(4);
q1.enqueue(64);
q1.displayQueue();
System.out.println("Insert at the end : ");
q1.enqueue(23);
q1.displayQueue();
System.out.println("Delete an element at the begining of the queue");
q1.dequeue();
q1.displayQueue();
}
}
What #pens-fan-69 said is true. I'd like to add on to that. In order to make your code work, all you have to do is make sure last is set to first during the first insert:
public void addEnd(int val) {
Node n1 = new Node(val);
if( isEmpty() ) {
first=last=n1;
} else {
last.setNext(n1);
last = n1;
}
}
I tried running the code in online compiler and it works: http://goo.gl/99FyfY
You need to set the last reference when inserting to the empty list. The NullPointerException is because you use last before ever setting it.
I have LinkedList with test program. As you can see in that program I add some Students to the list. I can delete them. If I choose s1,s2,s3 oraz s4 to delete everything runs well, and my list is printed properly and information about number of elements is proper. But if I delete last element (in this situation - s5) info about number of elements is still correct, but this element is still printed. Why is that so? Where is my mistake?
public class Lista implements List {
private Element head = new Element(null); //wartownik
private int size;
public Lista(){
clear();
}
public void clear(){
head.setNext(null);
size=0;
}
public void add(Object value){
if (head.getNext()==null) head.setNext(new Element(value));
else {
Element last = head.getNext();
//wyszukiwanie ostatniego elementu
while(last.getNext() != null)
last=last.getNext();
// i ustawianie jego referencji next na nowowstawiany Element
last.setNext(new Element(value));}
++size;
}
public Object get(int index) throws IndexOutOfBoundsException{
if(index<0 || index>size) throw new IndexOutOfBoundsException();
Element particular = head.getNext();
for(int i=0; i <= index; i++)
particular = particular.getNext();
return particular.getValue();
}
public boolean delete(Object o){
if(head.getNext() == null) return false;
if(head.getNext().getValue().equals(o)){
head.setNext(head.getNext().getNext());
size--;
return true;
}
Element delete = head.getNext();
while(delete != null && delete.getNext() != null){
if(delete.getNext().getValue().equals(o)){
delete.setNext(delete.getNext().getNext());
size--;
return true;
}
delete = delete.getNext();
}
return false;
}
public int size(){
return size;
}
public boolean isEmpty(){
return size == 0;
}
public IteratorListowy iterator() {
return new IteratorListowy();
}
public void wyswietlListe() {
IteratorListowy iterator = iterator();
for (iterator.first(); !iterator.isDone(); iterator.next())
{
System.out.println(iterator.current());
}
System.out.println();
}
public void infoOStanie() {
if (isEmpty()) {
System.out.println("Lista pusta.");
}
else
{
System.out.println("Lista zawiera " + size() + " elementow.");
}
}
private static final class Element{
private Object value;
private Element next; //Referencja do kolejnego obiektu
public Element(Object value){
setValue(value);
}
public void setValue(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
//ustawia referencję this.next na obiekt next podany w atgumencie
public void setNext(Element next) {
if (next != null)
this.next = next;
}
public Element getNext(){
return next;
}
}
private class IteratorListowy implements Iterator{
private Element current;
public IteratorListowy() {
current = head;
}
public void next() {
current = current.next;
}
public boolean isDone() {
return current == null;
}
public Object current() {
return current.value;
}
public void first() {
current = head.getNext();
}
}
}
test
public class Program {
public static void main(String[] args) {
Lista lista = new Lista();
Iterator iterator = lista.iterator();
Student s1 = new Student("Kowalski", 3523);
Student s2 = new Student("Polański", 45612);
Student s3 = new Student("Karzeł", 8795);
Student s4 = new Student("Pałka", 3218);
Student s5 = new Student("Konowałek", 8432);
Student s6 = new Student("Kłopotek", 6743);
Student s7 = new Student("Ciołek", 14124);
lista.add(s1);
lista.add(s2);
lista.add(s3);
lista.add(s4);
lista.add(s5);
lista.wyswietlListe();
lista.delete(s5);
lista.wyswietlListe();
lista.infoOStanie();
lista.clear();
lista.infoOStanie();
}
}
The problem is that your setNext(Element next) method does not set anything if next == null. And that is the case for the last element of your list.
So when you call delete.setNext(delete.getNext().getNext());, nothing is actually set because delete.getNext().getNext() is null!
Remove the if (next != null) condition in setNext and it will work.