How I can convert this doubly linked list into a doubly linked circular list?
public class DoublyLinkedList {
private Link first;
private Link last;
public DoublyLinkedList() {
first = null;
last = null;
}
public boolean isEmpty(){
return first == null;
}
public void insertFirst(long dd){
Link newLink = new Link(dd);
if (isEmpty())
last = newLink;
else
first.previous = newLink;
newLink.next = first;
first = newLink;
}
public void insertLast(long dd){
Link newLink = new Link(dd);
if (isEmpty())
first = newLink;
else {
last.next = newLink;
newLink.previous = last;
}
last = newLink;
}
public Link deleteFirst(){
Link temp = first;
if (first.next == null)
last = null;
else
first.next.previous = null;
first = first.next;
return temp;
}
public Link deleteLast(){
Link temp = last;
if (first.next == null)
first = null;
else
last.previous.next = null;
last = last.previous;
return temp;
}
public boolean insertAfter(long key, long dd) {
Link current = first;
while (current.dData != key){
current = current.next;
if (current == null)
return false; // cannot find it
}
Link newLink = new Link(dd); // make new link
if (current == last) // if last link,
{
newLink.next = null;
last = newLink;
} else // not last link,
{
newLink.next = current.next;
current.next.previous = newLink;
}
newLink.previous = current;
current.next = newLink;
return true; // found it, insert
}
public Link deleteKey(long key){
Link current = first;
while (current.dData != key)
{
current = current.next;
if (current == null)
return null; // cannot find it
}
if (current == first) // found it; first item?
first = current.next;
else
current.previous.next = current.next;
if (current == last) // last item?
last = current.previous;
else
// not last
current.next.previous = current.previous;
return current; // return value
}
public void displayForward() {
System.out.print("List (first to last): ");
Link current = first; // start at beginning
while (current != null) // until end of list,
{
current.displayLink();
current = current.next; // move to next link
}
System.out.println("");
}
public void displayBackward() {
System.out.print("List : ");
Link current = last;
while (current != null){
current.displayLink();
current = current.previous;
}
System.out.println("");
}
public static void main(String[] args) {
DoublyLinkedList theList = new DoublyLinkedList();
theList.insertFirst(22);
theList.insertFirst(44);
theList.insertLast(33);
theList.insertLast(55);
theList.displayForward();
theList.displayBackward();
theList.deleteFirst();
theList.deleteLast();
theList.deleteKey(11);
theList.displayForward();
theList.insertAfter(22, 77); // insert 77 after 22
theList.insertAfter(33, 88); // insert 88 after 33
theList.displayForward();
}
}
class Link {
public long dData; // data item
public Link next; // next link in list
public Link previous; // previous link in list
public Link(long d)
{
dData = d;
}
public void displayLink(){
System.out.print(dData + " ");
}
}
Thanks
The list, as is, doesn't provide a way to iterate over its elements. If it did, you could ask the list for an iterator and get the next element of the list from the iterator, until it reaches the last element. Making it circular would change the iterator behavior: it would go back to the first element once the last element is reached.
So, the answer is that to make it circular, you have to change the methods of the list so that the next link of the last one is the first one, an the previous link of the first one is the last one. But if you don't add other methods to the list, doing it won't change anything: the public behavior of the existing methods will stay the same once the list is made circular.
Related
I'm trying to implement delete() method in the LinkedList, which is a custom implementation of the Linked list data structure.
The following code seems to work properly if you delete the first element or an element in the middle. But if I'm trying to delete the last element in the LinkedList, it throws a NullPointerException.
How can I fix this problem?
My code:
public class LinkedList implements List {
Node first;
Node last;
int size;
public LinkedList() {
this.first = null;
this.last = null;
this.size = 0;
}
public void add(double element) {
Node newNode = new Node(element);
if (first == null) {
first = newNode;
last = newNode;
} else {
last.next = newNode;
last = newNode;
}
size++;
}
// more methods (unrelated to the problem)
public void delete(double element) {
if (first == null) {
return;
}
if (first.value == element) {
first = first.next;
return;
}
Node current = first;
Node previous = null;
while (current != null && current.next.value != element) {
previous = current;
current = current.next;
}
if (current == null) {
return;
} else {
current.next = current.next.next;
}
}
#Override
public String toString() {
if (first == null) {
return "[]";
} else {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (Node current = first; current != last; current = current.next) {
sb.append(current.value);
sb.append(",");
}
sb.append(last.value);
sb.append("]");
return sb.toString();
}
}
}
class LinkedListTest {
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add(5);
list.add(25);
list.add(-7);
list.add(80);
System.out.println(list);
list.delete(80);
System.out.println(list);
}
}
There are two issues in the implementation of the delete() method:
Condition of in the while-loop is not correct. Instead, checking if current != null you need to ensure that current.next is not null (note that it's safe to access the next property of current because iteration starts with current being assigned to first which is proved to be non-null).
You're not considering the edge-case when the Node to remove is the last one. In such a case, when control breaks out from the while-loop current.next would point to last Node, and that would mean the last field should be reassigned (since we're removing the last node).
Also, local variable previous is redundant.
public void delete(double element) {
if (first == null) {
return;
}
if (first.value == element) {
first = first.next;
return;
}
Node current = first;
while (current.next != null && current.next.value != element) {
current = current.next;
}
if (current.next == last) { // reassign last if the Node to be removed is the current last Node
last = current;
}
if (current.next != null) { // if the Node with given value was found
current.next = current.next.next;
}
}
I believe I have the code on how to remove an item in a linked list but I'm not sure how I can make it so that all occurrences of a value would be removed. Where would I need to make some changes that would have it check through all the values in the list?
I've tried to make an alternate or a dummy that pointed to the head but I wasn't sure where I was going with that.
public class LinkList {
private Link first; // ref to first link on list
// -------------------------------------------------------------
public LinkList() // constructor
{
first = null; // no links on list yet
}
// -------------------------------------------------------------
public void insertFirst(int id, double dd) {
Link newLink = new Link(id, dd);
newLink.next = first; // it points to old first link
first = newLink; // now first points to this
}
// -------------------------------------------------------------
public Link find(int key) // find link with given key
{ // (assumes non-empty list)
Link current = first; // start at 'first'
while (current.iData != key) // while no match,
{
if (current.next == null) // if end of list,
{
return null; // didn't find it
} else // not end of list,
{
current = current.next; // go to next link
}
}
return current; // found it
}
// -------------------------------------------------------------
public void displayList() // display the list
{
System.out.print("List (first-->last): ");
Link current = first; // start at beginning of list
while (current != null) // until end of list,
{
current.displayLink(); // print data
current = current.next; // move to next link
}
System.out.println("");
}
// -------------------------------------------------------------
public Link removeAll(int n) // delete link with given key
{ // (assumes non-empty list)
Link current = first; // search for link
Link previous = first;
while (current.iData != n) {
if (current.next == null) {
return null; // didn't find it
} else {
previous = current; // go to next link
current = current.next;
}
}
if (current == first) // if first link,
{
first = first.next; // change first
} else // otherwise,
{
previous.next = current.next; // bypass it
}
return current;
}
}
I expect to have all the values deleted for a given key but it I'm only able to delete one instance of a given value.
This removes all occurrences of Link with id == n. It should be the same if you want to remove by Link.iData.
public Link removeAll(int n)
{
Link head = first;
Link previous = null;
Link current = first;
while (current != null) {
if (current.id == n) {
if (previous == null) {
head = current.next;
} else {
previous.next = current.next;
}
} else {
previous = current; // if we removed current, let previous remain the same
}
current = current.next;
}
first = head;
return head;
}
Running the code like this:
LinkList l = new LinkList();
l.insertFirst(0, 0.1);
l.insertFirst(3, 3.1);
l.insertFirst(1, 1.1);
l.insertFirst(3, 3.1);
l.insertFirst(2, 2.1);
l.displayList();
l.removeAll(3);
l.displayList();
Outputs:
List (first-->last):
2 : 2.1
3 : 3.1
1 : 1.1
3 : 3.1
0 : 0.1
List (first-->last):
2 : 2.1
1 : 1.1
0 : 0.1
I have this class called ListNode, similar to yours.
public class ListNode {
public ListNode next;
public int val;
public ListNode removeAll(int n) {
ListNode newHead = null;
ListNode node = this;
//for keeping track of the node previous to the current node
ListNode prev = null;
//loop through the entire linked list
while (node != null) {
//when you encounter the val == n, delete the node
if (node.val == n) {
if (prev != null){
//this makes the previous node to point the node to the next of the current node
//if 2 -> 1 -> 3 and we have to remove node with key 1 and current node val == 1
// the following code will do this
// 2 -> 3
prev.next = node.next;
}
ListNode next = node.next;
//taking the same example
//this code will break the link : 1->3
node.next = null;
node = next;
} else {
if (newHead == null) {
newHead = node;
}
prev = node;
node = node.next;
}
}
return newHead;
}
}
You, basically, have to traverse through whole linked list, keeping track of the previous node for the current node and when you find a node with value/key/data equal to n, you make the previous node point to the next node of the current node and break the link of the current node to the next node.
Let's first start without deleting anything. To delete all occurrences, you first need to be able to iterate over the entire list (so you can look for multiple matches). Iterating over the whole list would simply be:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
// simply move to the next Link
previous = current; // store the current node as the previous for the next iteration
current = current.next; // move to the next link
}
}
Next, let's add in a check to see if the current Link is one that should be deleted:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
if (current.iData == n)
{
// To do...delete the current Link
}
else
{
// simply move to the next Link
previous = current; // store the current node as the previous for the next iteration
current = current.next; // move to the next link
}
}
}
Once we've found a match, there are two possibilities. Either the Link is the first Link, or it is somewhere further down in the list:
If the link is the first one, then we move current to the next Link, and make both first and previous point to the new current Link.
If we are not the first Link, then we move current to the next Link, and update the previous.next field to point to the new current Link (thus skipping over the Link to delete).
Here's the updated code:
public void removeAll(int n) // delete link with given key
{
Link current = first;
Link previous = first;
while (current != null)
{
if (current.iData == n)
{
if (current == first)
{
current = current.next;
first = current;
previous = current;
}
else
{
current = current.next;
previous.next = current;
}
}
else
{
// simply move to the next Link
previous = current;
current = current.next;
}
}
}
Here is simple recursive implementation (this implementation leaves initial list intact, and creates new without specified element):
public class Answer {
public static void main(String[] args) {
LinkedList list = new LinkedList(1, new LinkedList(2, new LinkedList(1, new LinkedList(2, new LinkedList(3, null)))));
System.out.println(list);
LinkedList withoutOne = list.removeAll(1);
System.out.println(withoutOne);
LinkedList withoutTwo = list.removeAll(2);
System.out.println(withoutTwo);
LinkedList withoutThree = list.removeAll(3);
System.out.println(withoutThree);
}
}
class LinkedList {
private int value;
private LinkedList next;
public LinkedList(int value, LinkedList next) {
this.value = value;
this.next = next;
}
public LinkedList removeAll(int value) {
if (this.next == null) {
return (this.value == value) ? null : new LinkedList(this.value, null);
} else if (this.value == value) {
return this.next.removeAll(value);
} else {
return new LinkedList(this.value, this.next.removeAll(value));
}
}
#Override
public String toString() {
String res = "LinkedList:";
for (LinkedList link = this; link != null; link = link.next) {
res += " " + link.value;
}
return res;
}
}
I'm going over data structures with my java book and i'm needing to recreate a circular linked list. I'm having issues with this linked list infinitely looping and cannot figure out why. I'm able to insert the values into the list, however printing and deleting the values seems to infinitely loop the values initially inserted. How can I change my List class to avoid infinitely looping?
Output:
30, 5, 15, 20, 10, 30, 5, 15, 20, 10, 30, 5, 15, 20, 10, ...
Main:
public static void main(String[] args) {
CircularList theList = new CircularList();
theList.insert(10);
theList.insert(20);
theList.insert(15);
theList.insert(5);
theList.insert(30);
theList.displayList();
System.out.println(theList.delete());
theList.delete(15);
theList.displayList();
while (!theList.isEmpty()) {
Link aLink = theList.delete();
System.out.println("Deleted: " + aLink);
}
if (!theList.isEmpty())
System.out.println("Program error");
else
System.out.println("Program success");
}
CircularList.class
class CircularList {
private Link current;
private Link prev;
public CircularList() {
// implement: set both current and prev to null
current = prev = null;
}
public boolean isEmpty() {
// implement
return (current == null); // true if current is empty
}
public void insert(int id) {
// implement: insert the new node behind the current node
Link newLink = new Link(id);
if (isEmpty()) {
prev = current = newLink;
} else {
prev.next = newLink;
newLink.next = current;
current = newLink;
}
}
public Link delete() {
// implement: delete the node referred by current
if (!isEmpty()) {
Link temp = current;
current = current.next;
return temp;
} else
return null;
}
public Link delete(int id) {
// implement: delete the node with value id
// if no node with the id exists, return null
if (isEmpty()) {
return null;
}
// Link current; // start probe at beginning
Link prev = current; // start previous at current
while (current != null && current.equals(current)) {
prev = current; //save previous link
current = current.next; // move to next Link
}
if (current == current.next)
current = current.next;
else if (current != null)
prev.next = current.next;
return current;
}
public void displayList() {
// implement: print all the list element values once, each value seperated by comma
while (current != null) {
System.out.printf(current + ", ");
current = current.next;
}
}
}
Link.class
class Link {
private int id;
Link next;
public Link(int id) {
// implement
this.id = id;
next = null;
}
public String toString() {
return String.valueOf(id);
}
}
It's a circular list, current will never be null in delete(int id) and displayList() unless the list is empty.
You'll have to remember where you started looking / printing and break if you get back to the starting Link.
Because a circle goes on forever you should probably set a start/stop index:
public void displayList() {
// implement: print all the list element values once, each value seperated by comma
Link start = current;
if (start == null)
return;
do {
System.out.printf(current + ", ");
current = current.next;
} while (current != start)
}
I am trying to write an insertion sort method but I am unable to seal the deal. Below is the code I have so far and I just cant seem to get the algorithm to work properly. The RecordList class contains all the methods for the linked list. Specificaly, Sort() works with a user defined object Student in which the students are sorted by ID numbers
public class RecordList {
private Link first; //ref to first item
private Link last; //ref to last item
int count = 0; //count number of elms in list
//constructor
public RecordList(){
first=null;
last=null;
}
//is empty
public boolean isEmpty(){
return first==null;
}
//insert first
public void insertFirst(Student dd){
count++;
Link newLink = new Link(dd); // make new link
if( isEmpty() ){ // if empty list,
last = newLink; // newLink <-- last
}
else{
first.previous = newLink; // newLink <-- old first
newLink.next = first; // newLink --> old first
first = newLink; // first --> newLink
}
}
//insert last
public void insertLast(Student dd){
count++;
Link newLink = new Link(dd); // make new link
if( isEmpty() ){ // if empty list,
first = newLink; // first --> newLink
}
else{
last.next = newLink; // old last --> newLink
newLink.previous = last; // old last <-- newLink
}
last = newLink; // newLink <-- last
}
//delete first
//ASSUMES NOT EMPTY
public Link deleteFirst(){
count--;
Link temp = first;
if(first.next == null){ // if only one item
last = null; // null <-- last
}
else{
first.next.previous = null; // null <-- old next
first = first.next; // first --> old next
}
return temp;
}
//delete last
//ASSUMES NOT EMPTY
public Link deleteLast(){
count--;
Link temp = last;
if(first.next == null){ // if only one item
first = null; // first --> null
}
else{
last.previous.next = null; // old previous --> null
last = last.previous; // old previous <-- last
}
return temp;
}
public boolean insertAfter(Student key, Student dd){ // (assumes non-empty list)
Link current = first; // start at beginning
while(current.dData != key){ // until match is found,
current = current.next; // move to next link
if(current == null){
return false; // didn’t find it
}
}
Link newLink = new Link(dd); // make new link
if(current==last){ // if last link,
newLink.next = null; // newLink --> null
last = newLink; // newLink <-- last
}
else{ // not last link,
newLink.next = current.next; // newLink --> old next
// newLink <-- old next
current.next.previous = newLink;
}
newLink.previous = current; // old current <-- newLink
current.next = newLink; // old current --> newLink
return true; // found it, did insertion
}
//self algorithm
public void Sort(){
Link marker = first;
Link current = null;
Link temp;
//if more than one elm sort
if(count > 1){
marker = marker.next;
//outer loop
//until end of list
while(marker != null){
current = marker.previous;
temp = marker;
//inner loop
//until position found
while(temp.dData.getID() > current.dData.getID()){
if(current == marker.previous){
marker = marker.next;
}
else{
marker = marker.next;
//remove temp from original position
if(temp.next == null){
last = temp.previous;
last.next = null;
}
else{
temp.previous.next = temp.next;
temp.next.previous = temp.previous;
}
//check to see if inserting to first elm or not
if(current == null){
//insert temp to first
//*****CHECK ALGORITHM*****\\
}
else{
//insert temp to current.next
temp.next = current.next;
temp.previous = current;
current.next.previous = temp;
current.next = temp;
}
}
}
//while/else DOES not work
else{
//if while condition not met
current = current.previous;
if(current == null){
//break to outer
}
else{
//break to inner
}
}
}
}
}
//display
#Override
public String toString(){
String s="";
Link current = first;
while(current != null){
s += current.dData+"\n"+"\n";
current = current.nextLink();
}
return s;
}
}
Sorry but your code looks like unnecessarily complicated. Also, your code contains a lot of more code than just 'sorting' on which your question is based. If "sorting" is your point of concern, try this. Otherwise feel free to downvote this answer, because Stack Overflow is only here to help you clear your concepts and then debug your own code.
This is the short and sweet code for Insertion sort (using array and JavaScript for easily checking in browser console). Check it in your browser console. And once you are clear with the idea, extend it for Linked List. Try to keep it simple like this and you will find your bug,
var a = [3,1,5,57,9,12,91,45,65,67,89,21,13,56,76,32,77,89,71];
console.log('array before sort...' + a);
//The Insertion Sort
for(var i=1; i<a.length; i++) {
var j = i-1;
var key = a[i];
while(j>=0 && a[j] > key) {
a[j+1] = a[j];
j--;
}
a[j+1] = key;
}
console.log('array after sort...' + a);
Just press F12 to open console in your browser. Paste this code and press Enter. Play with it to understand more.
Good Luck !!!
Here is my complete Java source code for implementing a singly linked list. I have seen many tutorials where they have been talking about inserting a node at the beginning. So, I decided to add a method insertAfterNode(int y) in my code where I can add data inside a node after a particular node.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package datastructures;
/**
*
* #author Administrator
*/
public class Link {
int data;
Link next;
public Link(int d) {
this.data = d;
}
public void display() {
System.out.println(data);
}
public static class LinkedList {
Link first;
public void insertItemFirst(int x){
Link newLink = new Link(x);
newLink.next = first;
first = newLink;
}
public Link deleteFirst() {
Link temp = first;
first = first.next;
return temp;
}
public void displayList() {
Link current = first;
while (current != null) {
current.display();
current = current.next;
}
}
// START Of METHOD
public void insertAfterNode(int y) {
// Considering LinkedList is Sorted
Link newNode = new Link(y);
Link current = first;
while (current != null) {
while (current.data < y) {
current = current.next;
newNode.next = current;
current = newNode;
}
}
}
//END Of METHOD
}
public static void main(String[] args) {
LinkedList addelements = new LinkedList();
addelements.insertItemFirst(20);
addelements.insertItemFirst(30);
addelements.insertItemFirst(40);
addelements.insertItemFirst(50);
addelements.insertAfterNode(44);
addelements.displayList();
System.out.println("After Calling Deletion Method Once ");
addelements.deleteFirst();
addelements.displayList();
}
}
The above code keeps on running in Netbeans and I had to stop the build to exit from it. I believe there is something wrong with my method implementation. Please let me know what's wrong with my following method:
public void insertAfterNode(int y) {
// Considering LinkedList is Sorted
Link newNode = new Link(y);
Link current = first;
while (current != null) {
while (current.data < y) {
current = current.next;
newNode.next = current;
current = newNode;
}
}
}
The code runs just fine without above method.
The current Link reference changes only if the y value is greater than the current.data. If the fist.data is, say, 10, and the y is 5, your code will never terminate.
You have to modify your while(current != null) cycle. Do not use the inner while.
Link newNode = new Link(y);
// "first" requires a special treatment, as we need to replace the "first" value
if(first.data > y){
// insert the new Link as first element
newNode.next = first;
first = newNode;
} else {
// we need the previous Link, because previous.next will be set to the newNode
Link previous = first;
Link current = first.next;
while (current != null) {
if(current.data < y) {
previous = current;
current = current.next;
} else {
// we insert newNode between previous and current
// btw. what should happen if current.data == y?
previous.next = newNode;
newNode.next = current;
break; // we are done, quit the cycle
}
}
// if the newNode.next is null at this point, means we have not inserted it yet.
// insert it as the last element in the list. previous is pointing at it.
if(newNode.next == null){
previous.next = newNode;
}
} // end of else
P.S. I hope it works, I have not tested the code :)