How to update rear in a circular linked list? - java

I need help updating the rear of a circular linked list if I move a set of nodes after the initial rear.
Lets assume rear is the rear node and rear.next circulates back to [1].
[1][2][3][4][5]
<-------------/
If I move [1][2][3] after node [5] giving me
[4][5][1][2][3], which breaks the circular linked list,
How can I approach updating [3] as rear and rear.next to point to [1]?

Because the nature of the set of links is a circle, you have to break the links and reestablish them after moving. The important links here are the ones that are going to be 'broken', which is (if it is a singly linked list, as I am assuming), the link from [3] -> [4] and the link from [5] -> [1].
You have two sections in your list here, [1][2][3], which we can call A, and [4][5], which we can call B. The --> link shown below is the pointer to the first element in the list.
--> A -> B -+
^ |
| |
+-------+
What you want to do is reset the link so that the last element in A points to the first element in B, and the last element in B points to the first element in A. In addition, the beginning of the list is now the first element in B.
--> B -> A -+
^ |
| |
+-------+
So now we just break and reset the links where they are needed.
--> [1][2][3] -> [4][5] -+ --> [4][5] -> [1][2][3] -+
^ | => ^ |
+-------------------+ +-------------------+
Set the beginning of the list to be the first element of B, which is [4]
Set the last element in B, which is [5], to point to the first element in A, which is [1]. This happens to already be set that way, but don't count on that. :)
Set the last element in A, which is [3], to point to the first element in B, which is [4].
As you can see, the only nodes we really care about are the first and last elements of each part of the list, i.e., the beginning and ending element of A and B. In this case, one of those sections also containd the first element, so we had to move the notion of which element was the 'first' element. Hope this helps.

Is this homework?
How are you doing the "move"?
I would make it a function, something like list.move(first, last, after), which in this case would be list.move(1, 3, 5).
And you'd have variables tracking the front/head and the rear/tail of the list. I'll assume they're called list.front and list.rear.
So in every case, you want to do:
list[after].next = list[first]
and then there's two special cases I can see:
inserting after the rear
(list[after] == list.rear)
moving the head
(list[start] == list.front)
So you can handle those using if statements.

I think this answers it(provided i understand this correctly)
Node insertAtRear(Node rear, T value) {
Node tmp = new Node(value);
if(rear!=null) {
tmp.next = rear.next;
rear.next = tmp
rear = tmp
} else {
// this is probably the first element to be inserted
rear = tmp;
rear.next = rear;
}
}

Working on the basis that you start with [1][2][3][4][5] and you want to end up with [4][5][1][2][3] you can do this using pointers and not change the data structure.
As you have indicated we have a circular list where the pointer "rear.next" points to the first bucket and each subsequent bucket has a .next pointer linking it to its right most neighbour until we get back to the rear bucket again. Basically a bunch of buckets linked to one another.
If we create a "tail" node and a "header" node we can use these to order the list. These are markers and not part of the circle they just point to a start or end point.
So to get [1][2][3][4][5] we can set the tail node to point to [5] then follow [5]s next pointer which leads us to [1] which we set our header to point to. So header=[1];tail=[5]
Starting at the header and working through the list following the next pointers each time we can access our items in this order [1][2][3][4][5]. No surprise there!
Lets change that though as we want [3] to be the rear. So lets set our tail node to point to [3]. Then follow [3]s next pointer we arrive at [4]. To this we assign the header.So header=[4];tail=[3]
Now working through our list starting with whatever our header points to we have [4][5][1][2][3].
It appears we have performed a move operation but we have not tampered with our data structure or its links - just the way we work with it. All we have altered is our header and tail. (Our pointers). Thats the beauty of the circular list.

Related

Why am i entering into an infinite loop when partitioning a linked list?

This is a common problem of partitioning a linked list into two parts. The list with nodes smaller than x will come first and the list of nodes larger than x will come after.
My question is - why do i need to set after.next to null after creating my two separate linked lists? Without setting it to null, I enter an infinite loop when trying to print this list.
My debugger shows that before_head.next has a never-ending list of nodes attached to it...
public Node partition(Node head, int x){
Node before_head=new Node(0);
Node before=before_head;
Node after_head=new Node(0);
Node after=after_head;
while(head != null){
if(head.val < x){
before.next=head;
before=before.next;
else{
after.next=head;
after=after.next;
}
head=head.next;
}
after.next=null;
before.next=after_head;
return before_head.next;
}
why do i need to set after.next to null after creating my two separate linked lists?
The last node of a linked list doesn't have a next node. In a linked list representation such as yours, that takes the form of the last node's next reference being null.
You are rearranging the existing nodes of the list by changing their next references. At the end of that process, after is a reference to the last node, therefore its next reference needs to be null. If it was also the last node in the original order then all is well -- its next reference is already null. If after was not the last node in the original order, however, then after.next will refer to one of the other nodes until you set it null. And whatever other node that is, it comes before after in the new order, forming a loop.
Note also that
before.next=after_head;
appears to be wrong. after_head is the dummy head node of the second partition, so you do not want to include it in the new list. I think you want
before.next = after_head.next;

Count number of nodes within given range in AVL tree

Suppose I have an AVL tree of distinct integers. I need to determine the number of nodes which lie in the interval [a, b) where a < b. Note that [a, b) is supplied by the user and hence I do not know beforehand what the value of a and b are. Also, a and b may not be present in the tree at all. For example, if I have a tree containing the integers {1, 2, 4, 5, 6, 7} then the user should expect an answer of 3 if he supplies the interval [3, 7).
A naive implementation would be to traverse every node and increment the count by 1 every time a node is found in the given interval. But this would have a worst case time complexity of O(n), as it is possible for every single integer in the tree to be within the given range. I need a faster algorithm, and after doing some research I found that it requires storing a size statistic in every node so that the rank of any given node can be easily computed.
I would like to do something like rank(b) - rank(a), but the problem is that a and b may not exist in the tree. In the above example, rank(7) would return 6 but rank(3) will not return any meaningful value.
Can anyone offer suggestions as to how I can address this issue? Also, I know that there is another similar question on this website, but that one involves C++ while this one involves Java. Also, I could not find a satisfactory answer there.
I've implemented a stack based tree iterator for an AVL tree some (long) time ago. It should work for your case like this:
create an array "treestack" which holds structs for traversal info. The struct just needs a bool "visited", and a pointer to your node type. The array can be of static size e.g. hold 64 info elements (one for each level of your tree, so this 64 will mean your tree contains max 4G nodes)
change the search method of your AVL tree to put the root node at treestack[0] when you begin with the search, and put all other nodes on top of the treestack as you follow the left and right child nodes during your search. Edit: Note that an unsuccessful search will result in your treestack having a node with the next smaller or next higher value, which is exactly what you want (just skip counting in case it's smaller, we still have abvalid iterator start oath).
You've now a path un your treestack which you can use for subsequent in-order traversal to find the next higher values. In-order traversal using the stack works like this:
start at the last element in treestack, keep a treeindex which is initially = arrayindex of the last item.
When there is a right node, and it is not marked visited: try follow ONE right of the current node, then ENDLESS to the left of any following nodes. Wherever you stop (so also if there are no left nodes but a single right one) is the next higher value. Put all nodes at the end of your tree stack as you follow them and inc your treeindex as you follow paths. And Mark the choosen final node with the next higher value as visited. Increase your node counter+1.
now to find subsequent higher values, ascend in the tree by taking treeindex-1 in your treestack as current node, an repeat the above step to find the next node with higher value.
if there is no right child node the current node, and the node is not marked visited: mark as visited, and inc node counter by 1
you're done when you either reach the root node with treeindex 0 or your node containing max value.
I hope it helps.
Instead of
rank(b) - rank(a)
what I would do is
rank(X) - rank(Y)
X is the very first node having value > b.
Y is the very first node having value >= a.

doubly linked list empty situation

In my lecture noes its given that if doubly linked list is empty then
header.next==tail;
Or
tail.prev==header;
But I feel like this is the case when there's exactly two nodes. Shouldn't the empty case be
head==null.
I don't know if I am correct.I am sill new to this subject.Can someone please clarify this
There are two common ways to store a double linked-list:
Let head and tail refer to actual nodes in the tree.
head variable tail variable
| |
V V
first -> second -> third -> null
In this case, you are correct - head will be null.
Let head and tail be special nodes (called "sentinel nodes", as pointed out in the other answer) which don't actually contain any data and point to the first and last nodes in the list through next and prev respectively.
head variable tail variable
| |
V V
head -> first -> second -> third -> tail -> null
node node
In this case, header.next == tail will mean the list is empty.
One might use this approach instead of the above one to simplify the implementation a bit and make the code a bit faster - there's no need to make special provision for removing or inserting the first or last nodes.
This doubly-linked list is using both head and tail sentinel nodes. These are nodes that don't actually contain elements of the list, but help to make certain algorithms slightly nicer by making the head and tail cases work more like the middle of the list.
If the list weren't using sentinels, then the empty case would be head==null, and the two-element case would have header.next==tail and tail.prev==header.

Find the 3rd last element in the Singly Link List - Algorithm

I am thinking on the Algo to find the 3rd last element in the Singly Link List and I come up with one by myself(space in-efficient)
Put the Link List in a ArrayList using a loop with O(n)time complexity [a lot of space complexity]
then find the size of Arraylist and retrieve the element[required element] at (size-2) index location
Please guide me if my algo make sense
FYI
Other I searched is :
Put two pointers and keep 1st pointer on 1st element and 2nd pointer on 3rd element and move them parallel
When the second pointer reaches the end of LinkList, retrieve the node[required node] which is pointed by the 1st pointer
Use two pointers: pointer-1 and pointer-2
make pointer-1 points to third node in single linked list.
pointer-1 = node1->next->next; // point to 3rd nd
node1-->node2-->node3-->node4---> ...... -->node-last
^
|
pointer-1
Now set pointer-2 points to first-node
pointer-2 = node1; // point to 1st nd
node1-->node2-->node3-->node4---> ...... -->node-last
^ ^
| |
pointer-2 pointer-1
Now, travel in linked list in a loop till pointer-1 points to last node, in loop also update pointer-2 (every time to next node of itself )
while (pointer-1->next!=NULL){// points to last node
pointer-1 = pointer-1 -> next;
pointer-2 = pointer-2 -> next;
}
When loop ends pointer-1 points to last-node, pointer-2 points to third last
node1-->node2-->........ ->node-l3-->node-l2-->node-last
^ ^
| |
pointer-2 pointer-1
It works in O(n) times, where n is number of nodes in linked-list.
Since the linked list is singly linked, you need to traverse it from the beginning to end to know what the 3rd to last element is, os O(n) time is unavoidable (unless you maintain a pointer to the 3rd to last element in your linked list).
Your 2 pointers idea, will use constant space. This is probably the better option, since creating an ArrayList will have more overhead, and use more space.
Get two pointers. pA, pB
Move pA to 3 elements advance and pB to the head:
1->2->3->4-> .... ->99->100
| |
pB pA
After this, move both pointers in the same loop till pA reaches to the last element.
At that point pB will be pointing to the last 3rd element
1->2->3->4-> .... ->98->99->100
| |
pB pA
Edited:
traversal will be one:
while(pA->next!=null){
pA = pA->next;
pB = pB->next;
}
Here pB will be 3rd last
An alternative view to solve this even though it is O(n)
Create an empty array(n), start a pointer into this array at 0, and start from the beginning of the linked list as well. Every time you visit a node store it in the current index of the array and advance the array pointer. Keep filling the nodes in the array, and when you reach the end of the array please start from the beginning again so as to overwrite.
Now once you end the final end of the list the pointer nth elemtn from end :)
In practice, a Java LinkedList keeps track of its size, so you could just go to 'list.get(list.size()-2)', but with a constructed linked list, I'd do the following:
Keep an array of 3 values. As you traverse the list, add the update the value at array[i%3]. When there are no more values, return the value at array[(i-2)%3].
The first thing I'd do is ask you to reconsider your use of a singly linked list. Why not just store your data in an ArrayList? It does everything you seem to want, and it's a builtin so it's relatively efficient compared to what most people would write.
If you were bound and determined to use a linked list, I'd suggest keeping a direct pointer to the 3rd last element (tle). Insertions are easy - if they come before the tle, do nothing; if after, advance the tle pointer to the tle's next. Removals are more of a hassle, but probably not most of the time. If the removal occurs before the tle, it's still the tle. The annoying situation is if the element to be removed is the tle or later, in which case you get to iterate through from the beginning until the next() reference of the current node is the tle. The current node will become the new tle, and you can then proceed with the removal. Since there are only three nodes which invoke this level of work, you'll probably do all right most of the time if the list is sizable.
A final option, if removals from the end are a frequent occurrence, is to maintain your list from back to front. Then the tle becomes the third from the front for maintenance purposes.
//We take here two pointers pNode and qNode both initial points to head
//pNode traverse till end of list and the qNode will only traverse when difference
// between the count and position is grater than 0 and pthNode increments once
// in each loop
static ListNode nthNode(int pos){
ListNode pNode=head;
ListNode qNode=head;
int count =0;
while(qNode!=null){
count++;
if(count - pos > 0)
pNode=pNode.next;
qNode=qNode.next;
}
return pNode;
}

Question about recursive implementation of reversing a singly linked list

If I have created a linked list where order of insertion is 5,4,3. I use the head reference so the linked list gets stored as 3->4->5->null.
When I want to reverse the linked list == original order of insertion so it will be
5->4->3->null. Now if this is how my new list looks like, which node should my head reference be referring to so the new elements I add to the list will still have O(1) insertion time?
I think head, by definition, always points to the first element of a list.
If you want to insert to the end of a linked list in O(1) then keep two references, one to the first element and one to the last element. Then adding to the end is done by following the last reference to the last element, add the new element beyond the last element, update the last reference to point to the new last element.
Inserting to an empty list becomes a special case because you have to set both first and last references not just the last reference. Similarly for deleting from a list with one element.
If you want to the back of a singly linked list, you should keep a reference to the last element. When you want to insert a new element, you create a new link object with the new element as head, the tail of the element you insert it after as the tail, and the new link object as the new tail of the element you insert it afterward. This takes three pointer movements and thus constant time.
For any linked list to have an O(1) insertion time, you have to insert into the front of the list or some other arbitrary location completely disregarding any order. Being a singly linked list means that you can't point to the last element in the list because the list up until the last element will be inaccessible. A fix to this might be as Shannon Severance has stated in that you keep two pointers, a head and a tail. You can use the head to access the elements and the tail to arbitrarily add elements to the list.
Think of it this way:
The reverse of a list consisting of HEAD -> [the rest of the list] is precisely: reverse([the rest of the list]) -> HEAD.
Your base case would be if the list contains a single element. The reverse of such a list is just itself.
Here's an example (using executable pseudo-code, aka Python):
class Node(object):
def __init__(self, data, next_=None):
self._data = data
self._next = next_
def __str__(self):
return '[%s] -> %s' % (self._data,
self._next or 'nil')
def reverse(node):
# base case
if node._next is None:
return node
# recursive
head = Node(node._data) # make a [HEAD] -> nil
tail_reverse = reverse(node._next)
# traverse tail_reverse
current = tail_reverse
while current._next is not None:
current = current._next
current._next = head
return tail_reverse
if __name__ == '__main__':
head = Node(0,
Node(1,
Node(2,
Node(3))))
print head
print reverse(head)
Note that this is not in O(1) due to the lack of a last-element reference (only HEAD).

Categories

Resources