Im trying to create a public bool remove(E element) method that removes the first node that includes the element and if no such a node is found it returns false otherwise true...How can I do that ? im having trouble linking the removed node's predecessor to its successor to close the gap created by the node's removal...this is my code so far...thank you
public class SinglyLinkedList<E> {
private final SLNode<E> head;
private final SLNode<E> tail;
int length;
// creates an empty list
public SinglyLinkedList() {
head = new SLNode<E>();
tail = new SLNode<E>();
head.setSuccessor(tail);
length = 0;
}
// adds new node on beginning of the list
public void add(E element) {
SLNode<E> node = new SLNode<E>(element, null);
node.setSuccessor(head.getSuccessor());
head.setSuccessor(node);
}
// adds new node on beginning of the list
public void add(SLNode<E> node) {
node.setSuccessor(head.getSuccessor());
head.setSuccessor(node);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
SLNode<E> cursor = head.getSuccessor();
while (cursor != tail) {
sb.append(cursor.getElement()).append(" ");
cursor = cursor.getSuccessor();
}
sb.append("\n");
return sb.toString();
}
}
slnode class
public class SLNode<E> {
private E element;
private SLNode<E> successor;
public SLNode() {
element = null;
successor = null;
}
public SLNode(E theElement, SLNode<E> theSuccessor) {
element = theElement;
successor = theSuccessor;
}
public E getElement() {
return element;
}
public void setElement(E newElement) {
element = newElement;
}
public SLNode<E> getSuccessor() {
return successor;
}
public void setSuccessor(SLNode<E> newSuccessor) {
successor = newSuccessor;
}
}
The trick is as you iterate, you need to keep a reference to both the previous and the current element. The reference to the previous element is what lets you close the gap:
public boolean remove(E element) {
SLNode<E> previous = head;
SLNode<E> current = head.getSuccessor();
while (current != tail) {
if (current.getElement().equals(element)) {
previous.setSuccessor(current.getSuccessor());
return true;
}
previous = current;
current = current.getSuccessor();
}
return false;
}
Related
This code allows me to create a linked list and I want to be able to add elements
between two nodes.
I'm having trouble understanding how to set it up so I can insert a number between 40 and 30.
public class DoublyLinkedList<E> {
private static class Node<E> {
//Node Fields
private E element;
private Node<E> prev;
private Node<E> next;
// Node Constructor
public Node(E e, Node<E> p, Node<E> n) {
this.element = e;
this.prev = p;
this.next = n;
}
// Node Methods
public E getElement() {
return element;
}
public Node<E> getPrev() {
return this.prev;
}
public Node<E> getNext() {
return this.next;
}
public void setPrev(Node<E> p) {
this.prev = p;
}
public void setNext(Node<E> n) {
this.next = n;
}
}
// DLinkedList Fields
private Node<E> header;
private Node<E> trailer;
int size;
// DLinkedList Constructor
public DoublyLinkedList() {
this.header = new Node<>(null, null, null);
this.trailer = new Node<>(null, this.header, null);
this.header.setNext(this.trailer);
}
// DLinkedList Methods
public int size() {
return this.size;
}
public E first() {
if (isEmpty()) {
return null;
}
return this.header.next.getElement();
}
public E last() {
if (isEmpty()) {
return null;
}
return this.trailer.prev.getElement();
}
public boolean isEmpty() {
return size == 0;
}
public void addFirst(E e) {
addBetween(e, this.header, this.header.getNext());
}
public void addLast(E e) {
addBetween(e, this.trailer.getPrev(), this.trailer);
}
public void addBetween(E e, Node<E> predecessor, Node<E> successor) {
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
this.size++;
}
public E removeFirst() {
if (this.isEmpty()) {
return null;
}
return this.remove(header.getNext());
}
public E removeLast() {
if (this.isEmpty()) {
return null;
}
return this.remove(trailer.getPrev());
}
public E remove(Node<E> e) {
e.next.setPrev(e.prev);
e.prev.setNext(e.next);
this.size--;
return e.getElement();
}
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = this.header.next;
while (walk != this.trailer) {
sb.append(walk.element);
if (walk.next != this.trailer)
sb.append("--> ");
walk = walk.next;
}
sb.append(")");
return sb.toString();
}
// Node myList = new Node<E>(null, trailer, header);
// myList.e.addFirst
// Node myList2 = new Node<E>(null, 1, null);
}
class Main {
public static void main(String[] args) {
// create a DoublyLinkedList object
DoublyLinkedList Node = new DoublyLinkedList();
// Add nodes to the list
Node.addFirst(10);
Node.addFirst(20);
Node.addFirst(30);
Node.addFirst(40);
Node.addFirst(50);
Node.removeFirst();
Node.removeLast();
//Node.addBetween(Node, null, null);
// print the nodes of DoublyLinkedList
System.out.println(Node);
}
}
Start by changing addBetween to return the node.
public Node<E> addBetween(E e, Node<E> predecessor, Node<E> successor) {
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
this.size++;
return newest;
}
Change addFirst and addLast to return that node. I'll only show addFirst:
public Node<E> addFirst(E e) {
return addBetween(e, this.header, this.header.getNext());
}
Save the nodes for 30 and 40:
Node<Integer> node30 = Node.addFirst(30);
Node<Integer> node40 = Node.addFirst(40);
Then you can use addBetween:
Node.addBetween(newNumber, node30, node40);
You need not expose the class Node and indeed you made it private.
But then you cannot navigate by Node, just by E. So remove(Node) is not possible as public method.
Node's methods could be private too.
Node need not be parametrized by <E>. That can even give serious programming problems, as there then are two Es. Remove it.
addBetween is nicely symmetric, but successor is redundant. I would remove it as parameter and make it a local variable.
Rename the local variable Node to list.
So:
private E removeNode(Node node) {
node.next.setPrev(node.prev);
node.prev.setNext(node.next);
size--;
return node.getElement();
}
private Optional<Node> find(E element) {
for (Node node = header.next; node != trailer; node = node.next) {
if (node.element == element) {
return Optional.of(node);
}
}
return Optional.empty();
}
public boolean remove(E e) {
Optional<Node> nodeOpt = find(e);
nodeOpt.ifPresent(n -> removeNode(n));
return nodeOpt.isPresent();
}
The same for an insertBefore(E), insertAfter(E).
Not sure how to fill in the last two methods at the bottom of this code. The findNode(E e) should return the Node that contains the element e, or it returns null if the list is empty. The last toString() method is meant to override a previous one in another class and prints the content of a list.
public class DoublyLinkedList<E> {
public static class Node<E> {
private E element; // reference to the element stored at
private Node<E> prev; // reference to the previous node in the
private Node<E> next; // reference to the subsequent node in
public Node(E element, Node<E> prev, Node<E> next) {
this.element = element;
this.prev = prev;
this.next = next;
}
// public accessor methods
public E getElement() {
return element;
}
public Node<E> getPrev() {
return prev;
}
public Node<E> getNext() {
return next;
}
// Update methods
public void setPrev(Node<E> p) {
prev = p;
}
public void setNext(Node<E> n) {
next = n;
}
} //----------- end of nested Node class -----------
// instance variables of the DoublyLinkedList
private Node<E> header; // header sentinel
private Node<E> trailer; // trailer sentinel
private int size = 0; // number of elements in the list
public DoublyLinkedList() {
header = new Node<>(null, null, null); // create header
trailer = new Node<>(null, header, null); // trailer is preceded by
header.setNext(trailer); // header is followed by
}
// public accessor methods
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void addLast(E e) {
addBetween(e, trailer.getPrev(), trailer); // place just before the
}
// public update methods
public void addBetween(E e, Node<E> predecessor, Node<E> successor) {
// create and link a new node
Node<E> newest = new Node<>(e, predecessor, successor);
predecessor.setNext(newest);
successor.setPrev(newest);
size++;
}
public Node<E> findNode(E e) {
E element = e;
if (isEmpty()) {
return null;
}
int node = 0;
Node<E> temp = header;
while (temp != null) {
if (temp.getNext() == element) {
return node;
}
node++;
temp = temp.getNext();
}
}
public String toString() {
ArrayList<E> ref = new ArrayList<>();
int counter = 1;
return ref.toString();
}
}
public class Node<E> {
private E element;
public Node<E> next;
int data;
Node(int d)
{
data = d;
next = null;
}
public Node(E element, Node<E> next) {
this.element = element;
this.next = next;
}
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
public void setElement(E element) {
this.element=element;
}
public void setNext(Node<E> n) {
next = n;
}
public void displayNode(){
System.out.print(element+ " ");
}
}
public class SinglyLinkedList<E> {
private Node<E> head;
private Node<E> tail;
private int size;
public SinglyLinkedList() {
head = tail = null;
size = 0;
}
public SinglyLinkedList(Node<E> head, Node<E> tail) {
this.head = head;
this.tail = tail;
}
public Node<E> getHead() {
return head;
}
public Node<E> getTail() {
return tail;
}
public void setHead(Node<E> head) {
this.head = head;
}
public void setTail(Node<E> tail) {
this.tail = tail;
}
public boolean isEmpty() {
if (head == null) {
return true;
}
return false;
}
public E first() {
return head.getElement();
}
public E last() {
return tail.getElement();
}
public void addFirst(E e) {
if (head == null) {
head = tail = new Node(e, null);
} else {
Node<E> newest = new Node(e, head);
head = newest;
}
size++;
}
public void addLast(E e) {
if (tail == null) {
head = tail = new Node(e, null);
} else {
Node<E> newest = new Node(e, null);
tail.setNext(newest);
tail = newest;
}
size++;
}
public E removeFirst() {
E e = head.getElement();
head = head.getNext();
size--;
return e;
}
#Override
public String toString() {
Node<E> tmp = head;
String s = "";
while (tmp != null) {
s += tmp.getElement();
tmp=tmp.getNext();
}
return s;
}
public void displayList() {
Node current = head;
while (current != null) {
current.displayNode();
current = current.next;
}
}
}
public interface Queue<E> {
int size();
boolean isEmpty();
void enqueue( );
E first();
E dequeue();
}
public class LinkedQueue<E> implements Queue<E> {
private SinglyLinkedList<E> list = new SinglyLinkedList<>();
public LinkedQueue() {
}
public int size() {
return list.size();
}
public boolean isEmpty() {
return list.isEmpty();
}
public void enqueue(E element) {
list.addLast(element);
}
public E first() {
return list.first();
}
public E dequeue() {
return list.removeFirst();
}
#Override
public void enqueue() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools |list.addLast(element);
}
public void displayQueue() {
list.displayList();
System.out.println();
}
public class Main {
public static void main(String[] args) {
LinkedQueue list = new LinkedQueue();
list.enqueue(sam);
list.enqueue(adams);
list.enqueue(john);
list.enqueue(isac);
list.enqueue(gad);
System.out.print("\n Linked list before calling swapNodes() ");
list.displayQueue();
}}
How to change the order of these names in the queue?
I have try to put function that swap nodes in the singlylinkedlist class but it didn't work.i m confused in which layer should i make this function in the linkedqueue class or the singlylinkedlist class or in the main class. yes i want just to swap names in the queue as simple as that.
UPDATED ANSWER
I modified your Node and NodeList Classes in a way which is easier to understand. I also kept similar private values and similar methods for those classes.
public class JavaApplication287 {
public static class Node{
private Node node;
private Node nextNode;
int data;
Node(int d){
data = d;
nextNode = null;
}
public Node getNode(){return node;}
public void setNode(Node someNode){node = someNode;}
public Node getNextNode(){return nextNode;}
public void setNextNode(Node someNextNode){nextNode = someNextNode;}
public int getData(){return data;}
public void setData(int d){data = d;}
public void printNode(){System.out.println(data);}
}
public static class NodeLinkedList{
private Node head;
private Node tail;
private int size;
NodeLinkedList(Node nodeHead, Node nodeTail, int s){
this.head = nodeHead;
this.tail = nodeTail;
this.size = s;
}
public Node getHead(){return head;}
public void setHead(Node n){head = n;}
public Node getTail(){return tail;}
public void setTail(Node n){tail = n;}
public int getSize(){return size;}
public void setSize(int n){size = n;}
public void printNodeList(){
System.out.println("Head: " + head.getData());
Node current = head;
while (current.nextNode != null){
System.out.println(current.data);
current = current.getNextNode();
}
System.out.println("Tail: " + tail.getData());
}
}
public static void main(String[] args) {
// create Sample Nodes
Node zero = new Node(0);
Node one = new Node(1);
Node two = new Node(2);
Node three = new Node(3);
Node four = new Node(4);
Node five = new Node(5);
//Link Them
zero.setNextNode(one);
one.setNextNode(two);
two.setNextNode(three);
three.setNextNode(four);
four.setNextNode(five);
//Create the Linked Node List with head = one & tail = five
NodeLinkedList myNodeLinkedList = new NodeLinkedList(zero, five, 6);
//Print Current LinkedNodes
myNodeLinkedList.printNodeList();
//Invert the NodeLinkedList
Node position = myNodeLinkedList.getHead(); //Node we look at
Node prev = null; // Store the prev Node
Node node = null; // Temp Node of the next Node in the Linked List
for (int i=0; i< myNodeLinkedList.getSize(); i++){
node = position.getNextNode(); //Store the Next Node so we do not lose access to it
position.setNextNode(prev); // Update current Node's NextNode value
prev = position; // Set previous Node as the Node we are currently looking at
position = node; // Move our position to the next Node
}
//Invert Head and Tail
Node temp = myNodeLinkedList.getHead();
myNodeLinkedList.setHead(myNodeLinkedList.getTail());
myNodeLinkedList.setTail(temp);
//Print Current LinkedNodes
myNodeLinkedList.printNodeList();
}
}
This is working code and here is the output I get,
run:
Head: 0
0
1
2
3
4
Tail: 5
Head: 5
5
4
3
2
1
Tail: 0
BUILD SUCCESSFUL (total time: 0 seconds)
Hope it helps,
I try to build an Linked Positional List myself when learning Data Structures and Algorithms in Java 6th Edition.
Position implements Node to store data.
I want to build two iterators,one for iterating Position and another for iterate the element in the Position. So I think two kinds of for-each loop could be applied as the following:
LinkedPositionalList<String> list = new LinkedPositionalList<>();
list.addFirst("A");
list.addLast("B");
list.addLast("V");
for (Position posi : list.positions()) {
}
for (String str:list ) {
}
It turns out that the second for-each not applicable to type,but the first one works well. So how to make the second for-each iterator work?
This is my code for building such class:
p.s.:The code is very long.The last part of nested class tried to implement the Iterator interface.The code before that is the way to build Linked Positional List which I think is not important...
public class LinkedPositionalList<E> implements PositionalList<E> {
private static class Node<E> implements Position<E> {
private E element;
private Node<E> prev;
private Node<E> next;
public Node(E e, Node<E> p, Node<E> n) {
element=e;
prev=p;
next=n;
}
public E getElement() throws IllegalStateException {
if (next == null) {
throw new IllegalStateException("Position no longer valid");
}
return element;
}
public Node<E> getPrev() {
return prev;
}
public Node<E> getNext() {
return next;
}
public void setElement(E e) {
element=e;
}
public void setPrev(Node<E> prev) {
this.prev = prev;
}
public void setNext(Node<E> next) {
this.next=next;
}
}
private Node<E> header;
private Node<E> trailer;
private int size=0;
public LinkedPositionalList() {
header = new Node<>(null, null, null);
trailer = new Node<>(null, header, null);
header.setNext(trailer);
}
private Node<E> validate(Position p)throws IllegalArgumentException {
if (!(p instanceof Node)) {
throw new IllegalArgumentException("Invalid p");
}
Node<E> node=(Node<E>)p;
if (node.getNext() == null) {
throw new IllegalArgumentException("p is no longer in the list");
}
return node;
}
private Position<E> position(Node<E> node) {
if (node == header || node == trailer) {
return null;
}
return node;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public Position<E> first() {
return position(header.getNext());
}
public Position<E> last() {
return position(trailer.getPrev());
}
public Position<E> before(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getPrev());
}
public Position<E> after(Position<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getNext());
}
public Position<E> addBetween(E e, Node<E> pred, Node<E> succ) {
Node<E> newest = new Node<>(e, pred, succ);
pred.setNext(newest);
succ.setPrev(newest);
size++;return newest;
}
public Position<E> addFirst(E e) {
return addBetween(e, header, header.getNext());
}
public Position<E> addLast(E e) {
return addBetween(e, trailer.getPrev(), trailer);
}
public Position<E> addBefore(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e, node.getPrev(), node);
}
public Position<E> addAfter(Position<E> p,E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e,node,node.getNext());
}
public E set(Position<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E answer = node.getElement();
node.setElement(e);
return answer;
}
public E remove(Position<E> p)throws IllegalArgumentException {
Node<E> node = validate(p);
Node<E> pre = node.getPrev();
Node<E> succ = node.getNext();
pre.setNext(succ);
succ.setPrev(pre);
size--;
E answer = node.getElement();
node.setNext(null);
node.setPrev(null);
node.setElement(null);
return answer;
}
//Here is the part that I think should be redesigned!!!!
private class PositionIterator implements Iterator<Position<E>> {
private Position<E> cursor = first(); // position of the next element to report
private Position<E> recent = null; // position of last reported element
public boolean hasNext() { return (cursor != null); }
public Position<E> next() throws NoSuchElementException {
if (cursor == null) throw new NoSuchElementException("nothing left");
recent = cursor; // element at this position might later be removed
cursor = after(cursor);
return recent;
}
public void remove() throws IllegalStateException {
if (recent == null) throw new IllegalStateException("nothing to remove");
LinkedPositionalList.this.remove(recent); // remove from outer list
recent = null; // do not allow remove again until next is called
}
} //------------ end of nested PositionIterator class ------------
//---------------- nested PositionIterable class ----------------
private class PositionIterable implements Iterable<Position<E>> {
public Iterator<Position<E>> iterator() { return new PositionIterator(); }
} //------------ end of nested PositionIterable class ------------
public Iterable<Position<E>> positions() {
return new PositionIterable(); // create a new instance of the inner class
}
//---------------- nested ElementIterator class ----------------
private class ElementIterator implements Iterator<E> {
Iterator<Position<E>> posIterator = new PositionIterator();
public boolean hasNext() { return posIterator.hasNext(); }
public E next() { return posIterator.next().getElement(); } // return element!
public void remove() { posIterator.remove(); }
}
public Iterator<E> iterator() { return new ElementIterator(); }
}
For the built-in Java Collection Framework classes, if you just want the items, use:
for (String item : list) {
// do something with item
}
To use an explicit iterator (so you could, for instance, use the iterator's remove() method), you use a regular for loop:
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
String item = iter.next();
// do something with item
}
Of course, you can also use a while loop.
For your particular class, it's hard to tell if the above applies because you haven't posted the definition of PositionalList.
Replace the inner loop with:
for (String str : list) {
}
That is the correct syntax for the Java for-each loop.
So I wrote my own linked list (and list node) in Java as a part of a homework.
Now, I'm trying to erase entries, but the function is not working.
I know the concept:
Search for node keeping the previous;
Tell previous node to point to next node;
Return or stop using the node so GC erases it.
For some reason it is not working. I can delete the node with the same value over and over. I'm afraid it is something related to Java pointers.
The code:
Node:
public class SimpleNode<E> {
private E value;
private SimpleNode<E> next;
public SimpleNode() {
this.value = null;
this.next = null;
}
public NoSimples(E data, SimpleNode<E> ref) {
this.value = data;
this.next = ref;
}
// Getters and Setters
}
List:
public class LinkedList<E> implements Iterable<SimpleNode<E>> {
private SimpleNode<E> head;
private int size = 0;
public LinkedList() {
this.head = new SimpleNode<E>();
}
public void add(SimpleNode<E> node) {
this.addFirst(node.getValue());
}
public void addFirst(E item) {
SimpleNode<E> nonde = new SimpleNode<E>(item, this.head);
this.head = node;
size++;
}
public void add(E value) {
this.addFirst(value);
}
public SimpleNode<E> removeFirst() {
SimpleNode<E> node = this.head;
if (node == null) {
return null;
} else {
this.head = node.getNext();
node.setNext(null);
this.size--;
return node;
}
}
public SimpleNodes<E> remove(E value) {
SimpleNode<E> nodeAnt = this.head;
SimpleNode<E> node = this.head.getNext();
while (node != null) {
if (node.getValue()!= null && node.getValue().equals(value)) {
nodeAnt.setNext(node.getNext());
node.setNext(null);
return node;
}
nodeAnt = node;
node = node.getNext();
}
return null;
}
// Other irrelevant methods.
}
Multiple Problems :
Think if you have a list 1,2,3,4. Now, if you try to remove 1, your code fails.
nodeAnt = node should be nodeAnt = nodeAnt.getNext(). Remember, the're all references, not Objects
Also, a recursive way might be easier to understand. For example, Here is how I implemented it
public void remove(E e){
prev = head;
removeElement(e, head);
System.gc();
}
private void removeElement(E e, Node currentElement) {
if(currentElement==null){
return;
}
if(head.getData().equals(e)){
head = head.getNext();
size--;
}else if(currentElement.getData().equals(e)){
prev.setNext(currentElement.getNext());
size--;
}
prev = prev.getNext();
removeElement(e, currentElement.getNext());
}
Note: I delete all occurrences of the Element, as I needed it. You may need it to be different.