Singly Linked List Reference Manipulation - java

I am Facing problems with Reference Manipulation:
First This is a Code Which takes a value x and traverses the List removing any Link with value Less than or Equal to X but it gives me a irregular output.Help is Appreciated.
public void rlx (int x){
Link p = head;//Initializing a pointer equal to head
for (Link c = head.next; c!=null;c=c.next) {//Initializing another Pointer with the Condition to termination
if((int)head.data<=x){//If the Value of head< = to X
head=head.next;//Skip the first and assign head to the second
}else if((int)c.data<=x){
p.next=c.next;//P.next skip c by pointing to c.next instead of c;
}
p=c; reinitialize p;
}
}
Main Method:
public static void main(String [] args){
LinkList l = new LinkList();
l.insertLast(1);
l.insertLast(2);
l.insertLast(3);
l.insertLast(4);
l.insertLast(3);
l.insertLast(2);
l.insertLast(1);
l.rlx(3);
System.out.print(l);
}
OutPut: [ 4, 2 ]

Your algorithm has a lot of issues, I'm really not sure where to start. First, you shouldn't be checking the head on each loop iteration, you should only be checking if c.data <= x. Second, you don't remove a node from a single linked list by simply pointing the previous pointer to the node that follows it. You should only be setting p = c if c.data > x not on every iteration. I generally have a rule against doing people's homework, but here
public void rlx (int x){
While(head != null && (int)head.data <= x) {
head = head.next
}
Link p = head;//Initializing a pointer equal to head
for (Link c = head.next; c!=null;c=c.next) {//Initializing another Pointer with the Condition to termination
if((int)c.data<=x){
p.next=c.next;//P.next skip c by pointing to c.next instead of c;
}
Else {
p=c;
}
}
}
I haven't bothered to test that because it's basically pseudo code, and I'm assuming your Link type is a pointer object. Basically, you need to do garbage collection explicitly, but more importantly you should be removing the head until you find a value that is larger than x in a while loop, then using a separate for loop to remove values after the head. Otherwise, if the head is smaller than x and c is smaller than x you'll remove the head, which will then become c, but since p is still the old head you'll update your list so that the old head points to the next value which is meaningless because nothing points to p and your current head would be c which isn't greater than x either. Then, p would then become c, which isn't greater than x. p should only ever point to the most recent Link found to be greater than x, and only replaced after you find a Link with value greater than x.

Related

Attempting to remove an Element at specific location in user-defined Doubly Linked List

This is from an old homework problem, that I already turned in, but I wasn't able to figure it out. I'm trying to remove an element from my LinkedList at a specific index using my user-defined class. Below is the pseudo code I'm working off of, but it doesn't have the same parameters as mine so I tried modifying it, but had an issue. I'm a programming noob (roughly 6 months of experience), just FYI. I understand ArrayLists just fine, but LinkedLists have been giving me trouble.
/*
* Remove the nth element in the list. The first element is element 1.
* Return the removed element to the caller.
function remove(List list, Node node)
if node.prev == null
list.firstNode := node.next
else
node.prev.next := node.next
if node.next == null
list.lastNode := node.prev
else
node.next.prev := node.prev
destroy node
*/
My method asks the user to enter an index position to delete. Because an int and LinkEntry are different types, naturally I'm having issues. I don't know how to incorporate the int that is passed through the parameter.
public void remove(int n)
{
LinkEntry<E> remove_this = new LinkEntry<E>();
remove_this.element = n;
for (remove_this = head; remove_this != null; remove_this = remove_this.next)
{
//removes the head if list is only 1 item long
if (head.next == null)
head = remove_this.next;
else
//sets previous element to the next element
remove_this.previous.next = remove_this.next;
//if nothing comes after remove_this, then remove the tail element
if (remove_this.next == null)
tail = remove_this.previous;
else
//sets next previous element to current previous element
remove_this.next.previous = remove_this.previous;
}
}
If you know of anywhere that gives another example that is more similar to what I'm trying to solve I would really appreciate it. I've looked through my text and online, but no luck.
You should set a counter to zero, browse your linked list from its first element (apparently named "head"), and increment the counter until its equal to n (or you reached the end of the list).
When counter equals to n, you must connect previous entry to next, and next to previous (so it deconnects the Nth). You also have to take care of special cases, when n=1 (you're supposed to delete "head" entry, that is to say set head to head.next), when next is null (n = list length), and when n negative or greater than list length.
When I learned this in galaxy far, far away ... it helped me to paint it on paper. Something like this:
You have
A B C
next *------>*------>*---->NULL
prev NULL<---*<------*-------*
and you want
A C
next *------>*---->NULL
prev NULL<---*<------*
So if you find B, you know what to do. But how to find B? B is the second element in our example above, so we'll be given a "1" in zero-based lists or a "2" in one-based lists.
A typical scenario would be to hold a reference to the first element of the list. This is often referred to as the "head". Now you would start with that head and follow its next-pointer. What do you get? The second element in the list. In our example that would already be our "B". Notice, that we followed next 1 time ... now assume we were to delete C. We got index 2 ( or one-based: 3) , we startet with head, followed next 1 time and got B. 1<2 so follow next again. Notice that we have to follow B's next instead of "head"'s So if using a loop, we'll have to use some sort of local var. Now we have the 2nd Element, which is C and remove it. Notice that C's "next" is null. So we are done in that direction.

Graph depth first search sometimes works, sometimes doesn't

So I wrote a Graph class and I can't seem to do a depth first search on it properly depending on the sequencing of nodes. Here's what I mean:
If my graph looks like this:
A-B-D
|/
C
The DFS returns: "ABC"
But when it looks like this:
A-B
| |
D C
|
E
It will print ABCDE correctly.
The problem I've found lies in my getUnvisitedAdjacentNode() function. Here is the function:
public int getUnvisitedAdjacentNode(int n) {
for (int i = 0; i < this.nodeList.size(); i++) {
if (this.edges[n][i] == 1 && this.nodeList.get(i).wasVisited == false) {
return i;
}
}
return -1;
}
The problem, I've found is because it goes in "order" (just a for loop) , it will never get traverse D in the first situation because B gets visited and after C gets visited, B simply get's popped off of the stack. Maybe this isn't the problem.
Here's the code for my actual DFS traversal.
public void depthFirstTraverse() {
Stack<Node> stack = new Stack<Node>();
nodeList.get(0).wasVisited = true;
System.out.println(nodeList.get(0).item);
stack.push(nodeList.get(0));
while (!stack.isEmpty()) {
int nextNode = this.getUnvisitedAdjacentNode(stack.peek().index);
if (nextNode == -1) {
stack.pop();
} else {
nodeList.get(nextNode).wasVisited = true;
System.out.println(nodeList.get(nextNode).item);
stack.push(nodeList.get(nextNode));
}
}
for (int i = 0; i < nodeList.size(); i++) {
nodeList.get(i).wasVisited = false;
}
}
Fortunately I found my own mistake, the code above is all correct, except it was in the code that I hadn't pasted.
In case anybody cares, the problem lied in the fact that I completely disregarded the fact that ArrayLists have an "IndexOf()" method (stupid, I know) and decided to hack my own "index" field into my Node class. When dealing with my own indices, I had a minor bug which screwed up the traversal.
So the old line in my DFS algorithm looks like this:
int nextNode = this.getUnvisitedAdjacentNode(stack.peek().index);
But it should be:
int nextNode = this.getUnvisitedAdjacentNode(this.nodeList.indexOf(stack.peek()));
You said it. If you pop a node off of the stack, you need to make sure that all of its unvisited neighbors are on the stack first. Otherwise, there's no guarantee that everyone will be visited.
For example, in the first diagram you gave, if node A is visited first, and then node B, either node C or D will be visited next. However, if you only push one of them onto the stack, and then remove B, there will be no way of reaching the last one.
So what you may want to do it write a function getAllUnvisitedAdjacentNodes and push all of them onto the stack before you pop.

Contents in an ArrayList get modified

I have a problem on a program I'm making that I honestly can't find a solution for. It seems the objects contained on a Java ArrayList collection are being modified without me programming such modifications.
The program as a whole is meant to basically create a random connection between two nodes on a 10x10 grid by moving through a path. This path is represented as an ArrayList collection of points in the grid, with the first index containing the first node's location (node A) and the last index containing the second node's location (node B). How I do this is by locating myself on A's location, and then moving randomly to contiguous points in the grid, repeating this in a while loop until B's location is reached.
Everything seems to work except that the "path" collection is altered somehow, such that every point in it ends up being the same as the last point to which I move, which is also B's location.
The method is as follows:
public void generateRandomPath()
{
path = new ArrayList<Point>();
path.add(pInitial);
complete = false;
while(!complete)
{
k = path.get(path.size()-1);
d = selectDirection(k);
GUI.log.append("==== Before the method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
x = move(k, d);
path.add(x);
if(k.getX() == pEnd.getX() && k.getY() == pEnd.getY())
complete = true;
}
GUI.log.append("Finished. \n");
}
"Point" are simply points, with an X
and Y coordinate represented by
integers.
"pInitial" is the point representing the location of node A.
"pEnd" is the point representing the location of node B.
"d" is the direction on which I'm going to move on this repetition. This can be either up, right, down, or left represented by an integer 1, 2, 3, and 4 respectively.
"k" is the last point in the path, which is the point to which it moved on the previous repetition.
"x" is the new point to which it moved on the current repetition.
So what it basically does is it grabs the last point in the path as reference, chooses a direction, and then moves to the point contiguous on that direction. Each repetition of the while loop should add a new point to path. However what ends up happening is that not only is this new point added, but every other point already in path takes the value of this last point added. By utilizing the log entries show above (GUI.log.append) I managed to see that path is being mysteriously altered inside the step:
x = move(k, d);
Which is the following method:
private Point move(Point n, int y)
{
GUI.log.append("==== Inside the method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
Point newP = n;
if(y == 1)
newP.setY(n.getY()-1);
if(y == 2)
newP.setX(n.getX()+1);
if(y == 3)
newP.setY(n.getY()+1);
if(y == 4)
newP.setX(n.getX()-1);
GUI.log.append("==== After method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
return newP;
}
Integer y is the direction as mentioned before. As you can see this method does not alter path in any way, yet the logs show it does. In this example node A was on the point X = 2, Y = 3. The log shows what the coordinates of the last point in path are. As you can see, the coordinates of the last point in path take on the value of the coordinates of the new point, but this new point was not yet added to path.
I honestly don't know how this is happening. If anyone could think of a reason I would appreciate it very much if you could tell me.
Try
Point newP = new Point(n.getX(), n.getY());
instead of
Point newP = n;

base case for recursive quicksort on singly linked list

I'm trying to get my head around a recursive quicksort on a singly linked list. What is the base case, and what do I need to do when I reach it in order for the function to 'rewind' and print a sorted list? Here is some code, but I think it's desperately wrong...
public static void qSort(SLLNode first, SLLNode last)
{
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
if (first!=last)
{
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
}
To rephrase my question: When I reach the base case first==last, what do I need to do? How can I make the recursion rewind and produce the sorted list?
Here's my updated code:
public static void qSort(SLLNode first, SLLNode last)
{
if (first==last)
{
return ;
}
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
while (head!=null)
{
if (head.data.compareToIgnoreCase(pivot.data)<0)
{
pivot.succ = head.succ ;
head.succ = first ;
first = head ;
qSort(first, pivot) ;
qSort(head, last) ;
}
qSort(first, pivot) ;
qSort(head, last) ;
}
}
In General
For a general review on quick-sort, you should probably review the quick-sort algorithm on Wikipedia. In short, it's easier if you use a partition helper function to get your list into a state where everything less than your pivot point is to the left of it, and everything greater than the pivot point is to the right of it. You then call quick-sort recursively with both sides of the pivot.
EJP also has a very good point. I haven't seen quick-sort on a linked list.
Let's Do It Anyway
The way I see a quick-sort with a linked-list, the algorithm would be something like
def qsort(head, tail)
if head == tail
return
pivot = tail
current = head
while current != pivot
if current.value < pivot.value
move/prepend current to head of the list
else
move/append current to tail of the list
current = current.next
qsort(head, pivot-1)
qsort(pivot, tail)
It gets a little tricky because you have to keep track of pivot - 1, which isn't very natural to do with a singly linked list. Also, the above algorithm doesn't really account for elements that are equal. But the general idea is that you end up with everything less than pivot being before it, and everything greater than it being after, and then you call qsort again for both sides.
Your Code
Let's run through your program with a simple case.
A->B->C->D
F L
Is our start.
SLLNode pivot = first ;
SLLNode head = pivot.succ ;
Gives us
A->B->C->D
F H L
P
Let's say if (head.data.compareToIgnoreCase(pivot.data)<0) is true for each element given the current state of the list.
So we enter the if statement, and do
pivot.succ = head.succ ;
A->C->D B->C
F L H
P
head.succ = first ;
B->A->C->D
H F L
P
first = head ;
B->A->C->D
H P L
F
This gives us
A->B->C->D
F H L
P
B->A->C->D
H P L
F
If I have that right, then the call to
qSort(head, last);
Should probably instead be
qSort(pivot, last);
So you're not calling qSort over the whole list again. It also seems like you might want to instead keep going through your list until everything that is less than the pivot is to the left of it, before recursively calling qSort.
Investigating Quicksort for a linked list is a useful thing. In studying any algorithm it is important to understand what is absolutely required.
In the case here one discovers that random access iterators are not required. Indeed forward iterators are sufficient.
A lot of Stepanov's work with the STL was to distill such information.
Here is a simple implementation in C++. Sorry for the change of language.
I'm just swapping data instead of node pointers. Doing the latter has nothing to do with Quicksort.
And yes, I know my choice of pivot element can cause problems.
One could find the distance, d, between first and last and then pick a random number x in the range [0, d). Now advance a pointer initialized to first x times, and swap its data with the data pointed to by first.
struct Node
{
Node(int d) : data(d), next(0) {}
~Node() { delete next; }
Node* next;
int data;
};
void Quicksort(Node* first, Node* last)
{
if (first == last)
{
return;
}
Node* pivot = first;
Node* boundary = first;
for (Node* it = first->next; it != last; it = it->next)
{
// Invariant:
// The iterators in the range [first, boundary->next)
// point to nodes with data less than the pivot
// element's.
// The iterators in the range [boundary->next, it)
// point to nodes with data greater or equal to
// the pivot element's.
if (it->data < pivot->data)
{
// Swap the data to maintain the invariant
boundary = boundary->next;
std::swap(it->data, boundary->data);
}
}
// Put the pivot data in its right place
std::swap(pivot->data, boundary->data);
Quicksort(first, boundary);
Quicksort(boundary->next, last);
}
The initial call would be something like
Quicksort(head, 0);
The base case is a list with 0 or 1 elements.
You don't need to "rewind." When you make a recursive call, it goes back up the recursion stack when the call finishes.
if(first==last) return;
Conceptually, note that in a base case where first==last, you have a linked list of one element and thus it is already sorted.
I think your algorithm may be slightly off?. You want a loop that moves everything less than the pivot to the first half, and everything greater to the second half. Then (after the loop is done!) you can recursively sort the halves. I see that yours is doing it a little differently, but I'm not convinced it's right....
Finally, as stated by others, sorting a linked list is not a very useful task. You wouldn't use a bike to tow a trailer....

how to go the middle of the singularly linked list in one iteration?

Recently I have been asked one question that in a singularly linked list how do we go to the middle of the list in one iteration.
A --> B --> C --> D (even nodes)
for this it should return address which points to B
A --> B --> C (odd nodes)
for this also it should return address which points to B
There is one solution of taking two pointers one moves one time and other moves two times but it does not seem working here
LinkedList p1,p2;
while(p2.next != null)
{
p1 = p1.next;
p2 = p2.next.next;
}
System.out.print("middle of the node" + p1.data); //This does not give accurate result in odd and even
Please help if anyone has did this before.
The basic algorithm would be
0 Take two pointers
1 Make both pointing to first node
2 Increment first with two node and first if its successful then traverse second to one node ahead
3 when second reaches end first one would be at middle.
Update:
It will definitely work in odd case, for even case you need to check one more condition if first point is allowed to move next but not next to next then both pointers will be at middle you need to decide which to take as middle
You can't advance p1 unless you successfully advanced p2 twice; otherwise, with a list length of 2 you end up with both pointing at the end (and you indicated even length lists should round toward the beginning).
So:
while ( p2.next != null ) {
p2 = p2.next;
if (p2.next != null) {
p2 = p2.next;
p1 = p1.next;
}
}
I know you've already accepted an answer, but this whole question sounds like an exercise in cleverness rather than an attempt to get the correct solution. Why would you do something in O(n) when you can do it in O(n/2)?
EDIT: This used to assert O(1) performance, and that is simply not correct. Thanks to ysth for pointing that out.
In practice, you would do this in zero iterations:
LinkedList list = ...
int size = list.size();
int middle = (size / 2) + (size % 2 == 0 ? 0 : 1) - 1; //index of middle item
Object o = list.get(middle); //or ListIterator it = list.listIterator(middle);
The solution of taking two pointers and one moves a half the rate should work fine. Most likely it is not the solution but your actual implementation that is the problem. Post more details of your implementation.
static ListElement findMiddle(ListElement head){
ListElement slower = head;
ListElement faster = head;
while(faster.next != null && faster.next.next !=null ){
faster = faster.next.next;
slower = slower.next;
}
return slower;
}
public static Node middle(Node head){
Node slow=head,fast=head;
while(fast!=null& fast.next!=null && fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
if(fast!=null && fast.next!=null){
slow=slow.next;
}
return slow;
}
public ListNode middleNode(ListNode head) {
if(head == null) return head;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}

Categories