I created a Doubly Circular Linked List.
I need to know the distance from every node to head.
Because when I must delete or get a node with a specific key, if 2 nodes have the same key and same distance, both must be deleted or got, otherwise must be deleted the node closest to head.
I don't know how to calculate the distance because is circular ...
The insertion of this Linked List work in this way.
All the nodes go after the Head.
Example :
1) Head
2) Head-A (Inserted A)
3) Head-B-A (Inserted B)
4) Head-C-B-A (Inserted C)
For now, i did only a normal cancellation without the distance.
This is my code.
/* Function to delete node with the key */
public void deleteWithKey(int key) {
if (key == head.getData()) {
if (size == 1) {
head = null;
end = null;
size = 0;
return;
}
head = head.getLinkNext();
head.setLinkPrev(end);
end.setLinkNext(head);
size--;
return;
}
if (key == end.getData()) {
end = end.getLinkPrev();
end.setLinkNext(head);
head.setLinkPrev(end);
size--;
}
Node current = head.getLinkNext();
for (int i = 2; i < size; i++) {
if (key == current.getData()) {
Node p = current.getLinkPrev();
Node n = current.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
size--;
return;
}
current = current.getLinkNext();
}
System.out.println("Don't exist a node with this key");
}
Thanks to All.
You actually don't need to know the distance. Rather, you need to find the closest to head.
Since it's a circular doubly linked list, this task is trivial:
define two variables a and b, initializing both to head
if either are the target, remove matching nodes and exit
assign a = a.next and b = b.previous
goto 2
This is the pseudocode I could think of to solve the problem.
Given head,
// no data
if(head==null) return;
// next and prev are always at same distance
next = head;
prev = head.prev;
// ensure nodes are not same or crossed half way through the list
while (next == prev || next.prev == prev){
// delete nodes if values are same
if (next.val == prev.val){
if(next!=head) {
next.prev.next = next.next;
next.next.prev = next.prev;
prev.prev.next = prev.next;
prev.next.prev = prev.prev;
}
// list has only two nodes
else if(head.next==prev){
head = null;
return;
// remove head and its prev node
else{
head = head.next;
head.prev = prev.next;
head.prev.next = head
}
}
// traverse through the list
next = next.next
prev = prev.prev
}
This is the final working code that i did.
Have you improvements?
Thanks to all for the help.
Complexity = O(n)
/* Function to delete node with the key */
public void deleteWithKey(int key) {
if (key == head.getData()) {
if (size == 1) {
head = null;
end = null;
size = 0;
return;
}
head = head.getLinkNext();
head.setLinkPrev(end);
end.setLinkNext(head);
size--;
return;
}
if (key == end.getData()) {
end = end.getLinkPrev();
end.setLinkNext(head);
head.setLinkPrev(end);
size--;
}
Node next = head;
Node back = head;
while (next != end) {
next = next.getLinkNext();
back = back.getLinkPrev();
if ((key == next.getData()) && (key == back.getData()) && (next != back)) {
Node p = next.getLinkPrev();
Node n = next.getLinkNext();
Node p1 = back.getLinkPrev();
Node n1 = next.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
p1.setLinkPrev(n1);
n1.setLinkPrev(p1);
size -= 2;
return;
}
if ((key == next.getData()) && (next != back)) {
Node p = next.getLinkPrev();
Node n = next.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
size--;
return;
}
if ((key == next.getData()) && (next == back)) {
Node p = next.getLinkPrev();
Node n = next.getLinkNext();
p.setLinkNext(n);
n.setLinkPrev(p);
size--;
return;
}
}
System.out.println("Don't exist a node with this key");
}
Related
I'm having a problem deleting nodes from singly linked lists in Java. I have a list, which has data of integers, and I need to delete all nodes, whose value can be divided by divided by four. I also need to move the head and tail pointers in case either of the head or tail elements are deleted. I wrote method for this, and most of the time it works just like I need it to, but sometimes it throws NullPointerException. How can I fix it? Here's my code:
public void delete(){
Node temp = head, prev = null;
if (temp != null && temp.data % 4 == 0)
{
head = temp.next;
temp = head;
}
while (temp.next != null)
{
if (temp.data % 4 != 0) {
prev = temp;
temp = temp.next;
}
else {
prev.next = temp.next;
temp = prev.next;
}
}
if (tail.data % 4 == 0) {
tail = prev;
tail.next = null;
}
}
while (temp.next != null): temp may be null. And some more small problems.
This is due to too much complexity.
public void delete() {
Node prev = null;
for (Node temp = head; temp != null; temp = temp.next) {
if (temp.data % 4 == 0) {
if (prev == null) {
head = temp.next;
} else {
prev.next = temp.next;
}
} else {
prev = temp;
}
}
tail = prev;
}
The above sets prev to the valid previous node.
The deletion considers deletion from head or from prev.next.
The tail is updated to the last element.
in your while condition add one more null check:
while (null != temp && null != temp.next)
As I've just started programming a few months back a lot of new information is coming and I'm having trouble catching up.So here I have created what I thought was a sorted linked list.Turns out it is not sorted
public boolean insert(Person person) {
Node n = new Node(person);
Node p = head;
if(p == null) {
head = n;
size++;
return true;
} else {
Node temp = p;
int comparison;
while(temp.next != null) {
comparison = temp.person.name.compareTo(person.name);
if(comparison == 0){
return false;
}
temp = temp.next;
}
temp.next = n;
size++;
return true;
}
}
The method works,it inserts the persons,but they arent sorted like they should be.What part of the code do I need to change/remove in order to make it sort.
Thanks!
You should insert like this:
static boolean insert(Person person) {
Node newNode = new Node(person);
if (head == null) {
head = newNode;
size++;
return true;
}
Node current = head;
Node prev = null;
int comparison;
while (current != null) {
comparison = person.name.compareTo(current.person.name);
if (comparison == 0) {
return false;
} else if (comparison > 0) { /// greater than
if (current.next == null) { // check if reach tail of the linked list add and break
current.next = newNode;
break;
}
} else { // less then
if (prev == null) { // check if it should be first then put and break
Node oldHead = head;
head = newNode;
head.next = oldHead;
break;
}
prev.next = newNode;
newNode.next = current;
break;
}
prev = current;
current = current.next;
}
size++;
return true;
}
There is a problem in your else part. You are returning false when same value is given. But it is not interpreted properly for a valid case.
You need to have as below.
Check current node value - Check for null pointer exception
Check next node value - Check for null pointer exception
If current input is between currentNode and nextNode then do insert between.
If reaches last node, then insert at the end
// Complete the sortedInsert function below.
/*
* For your reference:
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode next;
* DoublyLinkedListNode prev;
* }
*
*/
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode Leader=head;
DoublyLinkedListNode newNode = new DoublyLinkedListNode(data);
while(Leader.next!=null){
if(data>Leader.data){
Leader = Leader.next;
}
else {
if(Leader.prev == null) {
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
if(Leader.next == null) {
if(data<Leader.data) {
newNode.prev = Leader.prev;
newNode.next = Leader;
Leader.prev.next = newNode;
return head;
} else {
newNode.prev = Leader;
Leader.next = newNode;
return head;
}
}
return head;
}
in the above-sorted insert method how to decrease this doubly linked list complexity, this is a hackerrank question I'm getting timed outs for the test cases I need help in decreasing the time complexity for this code.
You code will never come out of while loop.
Lets take the example. List = [(1), (4), (4)](only 1 element). New node is (4). Your result should be [(1), (4), (4), (4)]. But lets walk your code and check what will happen. Initially Leader = (1)
while(Leader.next!=null){ // 1
if(data>Leader.data){ // 3
Leader = Leader.next;
}
else { // 6
if(Leader.prev == null) { // 7
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
At line 1 check will pass (as (1).next is not null; in fact it is (4)).
At line 3 ((4) > (1)). Check pass. Leader = (1).next = (4). Jump to line 1
At line 1 check will pass (as (4).next is not null; in fact it is (4)).
At line 3 ((4) > (4)). Check Fail. Enter line 7
At line 7 check will fail ((4).prev is not null; in fact it is (4) - 1st 4). No update in Leader will take place. Leader will remain same & you will enter infinte loop from here.
You will have to take care of this. Maybe the Problem's discussion page will help. But do give it a through try.
My own try is included below:
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode n = new DoublyLinkedListNode();
n.data = data;
DoublyLinkedListNode curr = head;
if (head == null) {
return n;
}
// if given node is smaller than 1st node
if (data < curr.data) {
n.next = curr;
return n;
}
// find first node greater than given node
while (curr.next != null && curr.data < data) {
curr = curr.next;
}
// reached to the end.
if (curr.next == null && data >= curr.data) {
curr.next = n;
} else { // found the 1st node which is greater than given node
curr.prev.next = n;
n.next = curr;
}
return head;
}
I'm trying to implement a doubly linked list for a class assignment. I am currently stuck on implementing a method to remove a node at a specified index.
public void remove(int index) {
if (index < 0 || index > count-1) {
throw new ListIndexOutOfBoundsException("The index "+index+" is out of bounds.");
}
if (isEmpty()) {
System.out.println("List is empty");
return;
}
MedicationNode curr = head;
int k = 0;
while(k < index) {
curr = curr.next;
k++;
}
if (curr.prev == null) {
curr.next.prev = null;
}else if(curr.next == null) {
curr = curr.prev;
curr.next = null;
}else{
curr.next.prev = curr.prev;
curr.prev.next = curr.next;
}
count--;
}
the method can remove any specified node in a linked list except index 0. I'm thinking the problem may be with my add method but im not really sure.
In your first if condition -
if (curr.prev == null) {
curr.next.prev = null;
//Make your head of the linked list point to this node
head = curr.next;
}
This is because you are removing the head from the list so the head should point to the head's next node.
I have a ordered binary tree:
4
|
|-------|
2 5
|
|-------|
1 3
The leaves point to null. I have to create a doubly link list which should look like
1<->2<->3<->4<->5
(Obviously 5 should point to 1)
The node class is as follows:
class Node {
Node left;
Node right;
int value;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
As you can see the doubly link list is ordered (sorted) as well.
Question: I have to create the linked list form the tree without using any extra pointers. The left pointer of the tree should be the previous pointer of the list and the right pointer of the tree should be the next pointer of the list.
What I thought off: Since the tree is an ordered tree, the inorder traversal would give me a sorted list. But while doing the inorder traversal I am not able to see, where and how to move the pointers to form a doubly linked list.
P.S I checked some variations of this question but none of them gave me any clues.
It sounds like you need a method that accepts a Node reference to the root of the tree and returns a Node reference to the head of a circular list, where no new Node objects are created. I would approach this recursively, starting with the simple tree:
2
|
|-----|
1 3
You don't say whether the tree is guaranteed to be full, so we need to allow for 1 and/or 3 being null. The following method should work for this simple tree:
Node simpleTreeToList(Node root) {
if (root == null) {
return null;
}
Node left = root.left;
Node right = root.right;
Node head;
if (left == null) {
head = root;
} else {
head = left;
left.right = root;
// root.left is already correct
}
if (right == null) {
head.left = root;
root.right = head;
} else {
head.left = right;
right.right = head;
right.left = root;
}
return head;
}
Once it is clear how this works, it isn't too hard to generalize it to a recursive method that works for any tree. It is a very similar method:
Node treeToList(Node root) {
if (root == null) {
return null;
}
Node leftTree = treeToList(root.left);
Node rightTree = treeToList(root.right);
Node head;
if (leftTree == null) {
head = root;
} else {
head = leftTree;
leftTree.left.right = root;
root.left = leftTree.left;
}
if (rightTree == null) {
head.left = root;
root.right = head;
} else {
head.left = rightTree.left;
rightTree.left.right = head;
rightTree.left = root;
root.right = rightTree;
}
return head;
}
If I got all the link assignments covered correctly, this should be all you need.
Do an in-order traversal of the list, adding each list item to the doubly linked list as you encounter it. When done, add an explicit link between the first and last items.
Update 3/6/2012: Since you must reuse the Node objects you already have, after you put the node objects into the the list, you can then iterate over the list and reset the left and right pointers of the Node objects to point to their siblings. Once that is done, you can get rid of the list and simply return the first node object.
This should also work:
NodeLL first = null;
NodeLL last = null;
private void convertToLL(NodeBST root) {
if (root == null) {
return;
}
NodeLL newNode = new NodeLL(root.data);
convertToLL(root.left);
final NodeLL l = last;
last = newNode;
if (l == null)
first = newNode;
else {
l.next = newNode;
last.prev = l;
}
convertToLL(root.right);
}
Let your recursion return the left and right end of formed list. Then you link your current node to the last of the left list, and first of the right list. Basic case it, when there is no left or right element, which is the node it self for both. Once all is done, you can link the first and last of the final result. Below is the java code.
static void convertToSortedList(TreeNode T){
TreeNode[] r = convertToSortedListHelper(T);
r[1].next = r[0];
r[0].prev= r[1];
}
static TreeNode[] convertToSortedListHelper(TreeNode T){
TreeNode[] ret = new TreeNode[2];
if (T == null) return ret;
if (T.left == null && T.right == null){
ret[0] = T;
ret[1] = T;
return ret;
}
TreeNode[] left = TreeNode.convertToSortedListHelper(T.left);
TreeNode[] right = TreeNode.convertToSortedListHelper(T.right);
if (left[1] != null) left[1].next = T;
T.prev = left[1];
T.next = right[0];
if (right[0] != null) right[0].prev = T;
ret[0] = left[0]==null? T:left[0];
ret[1] = right[1]==null? T:right[1];
return ret;
}
Add the following method to your Node class
public Node toLinked() {
Node leftmost = this, rightmost = this;
if (right != null) {
right = right.toLinked();
rightmost = right.left;
right.left = this;
}
if (left != null) {
leftmost = left.toLinked();
left = leftmost.left;
left.right = this;
}
leftmost.left = rightmost;
rightmost.right = leftmost;
return leftmost;
}
EDIT By maintaining the invariant that the list returned by toLinked() has the proper form, you can easily get the left- and rightmost nodes in the sublist returned by the recursive call on the subtrees
/* input: root of BST. Output: first node of a doubly linked sorted circular list. **Constraints**: do it in-place. */
public static Node transform(Node root){
if(root == null){
return null;
}
if(root.isLeaf()){
root.setRight(root);
root.setLeft(root);
return root;
}
Node firstLeft = transform(root.getLeft());
Node firstRight = transform(root.getRight());
Node lastLeft = firstLeft == null ? null : firstLeft.getLeft();
Node lastRight= firstRight == null ? null : firstRight.getLeft();
if(firstLeft != null){
lastLeft.setRight(root);
root.setLeft(lastLeft);
if(lastRight == null){
firstLeft.setLeft(root);
}
else{
firstLeft.setLeft(lastRight);
root.setRight(firstRight);
}
}
if(firstRight != null){
root.setRight(firstRight);
firstRight.setLeft(root);
if(lastLeft == null){
root.setLeft(lastRight);
lastRight.setLeft(root);
firstLeft = root;
}
else{
root.setLeft(lastLeft);
lastRight.setRight(firstLeft);
}
}
return firstLeft;
}