LinkedList pointer explanation - linked-list

So I get a little idea of how a linked list work and how the head node points to another node that contains data and also the address of the next node. I've also looked at examples. I've been looking at this code I found for the past five hours confused on how under the display() method that current = head points to the next node. I keep thinking head.next = null and doesn't point at the next node. Can someone explain to me how head.next is pointing to the next node or when did it acquired the address because I can't find when in the code it does.
public class SinglyLinkedList {
//Represent a node of the singly linked list
class Node{
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
//Represent the head and tail of the singly linked list
public Node head = null;
public Node tail = null;
//addNode() will add a new node to the list
public void addNode(int data) {
//Create a new node
Node newNode = new Node(data);
//Checks if the list is empty
if(head == null) {
//If list is empty, both head and tail will point to new node
head = newNode;
tail = newNode;
}
else {
//newNode will be added after tail such that tail's next will point to newNode
tail.next = newNode;
//newNode will become new tail of the list
tail = newNode;
}
}
//display() will display all the nodes present in the list
public void display() {
//Node current will point to head
Node current = head;
if(head == null) {
System.out.println("List is empty");
return;
}
System.out.println("Nodes of singly linked list: ");
while(current != null) {
//Prints each node by incrementing pointer
System.out.print(current.data + " ");
current = current.next;
}
System.out.println();
}
public static void main(String[] args) {
SinglyLinkedList sList = new SinglyLinkedList();
//Add nodes to the list
sList.addNode(1);
sList.addNode(2);
sList.addNode(3);
sList.addNode(4);
//Displays the nodes present in the list
sList.display();
}
}

When you iterate through the linked list the first time, head points to the firstNode. Then as the while loop runs, the code updates the pointer("Current") to point to the next Node. This is shown where you see current = current.next; The loops keep running until current points to null, after which it ends. Hope you understand better.

You are right that head.next is not directly assigned. However, tail.next is. Let's see what happens in addNode() for two cases:
When the list is empty and you add a node, both head and tail are set to the newNode. Keep in mind that (this being Java) head and tail are references to the object newNode, that is, they reference the same object.
When there is already 1 element in the list, and you add a new node (the second one) you set tail.next = newNode. Now remember that head and tail are references to the same object (the first one added so far). They are basically two names for the same thing at this moment. So what really happens is that the object referenced by head and tail gets its next member set to newNode - and now both head.next and tail.next point to newNode. After that tail itself is made to reference tne newNode and at this moment head and tail start to reference different objects - head still referencing the first element, and tail now referencing the second (and so far last) element.
Now when you get to display(), you see that head is really a reference to the first element of the list, its next points to the second one and so on...

Related

Generic Linked Lists find duplicates

Good day all,
I am studying Bsc-IT but am having problems.
With the current covid-19 situation we have been left to basically self-study and I need someone to put me in the right direction (not give me the answer) with my code.
I must write a program called appearsTwice that receives a linked list as parameter and return another list containing all the items from the parameter list that appears twice or more in the calling list.
My code so far(am I thinking in the right direction? What must I look at?)
public MyLinkedList appearsTwice(MyLinkedList paramList)
{
MyLinkedList<E> returnList = new MyLinkedList<E>(); // create an empty list
Node<E> ptrThis = this.head;//Used to traverse calling list
Node<E> ptrParam= paramList.head; //neither lists are empty
if (paramList.head == null) // parameter list is empty
return returnList;
if (ptrThis == null) //Calling list is empty
return returnList;
for (ptrThis = head; ptrThis != null; ptrThis = ptrThis.next)
{
if (ptrThis == ptrThis.element)
{
returnList.append(ptrThis.element);
}
}
Some issues:
Your code never iterates through the parameter list. The only node that is visited is its head node. You'll need to iterate over the parameter list for every value found in the calling list (assuming you are not allowed to use other data structures like hashsets).
if (ptrThis == ptrThis.element) makes little sense: it tries to compare a node with a node value. In practice this will never be true, nor is it useful. You want to compare ptrParam.element with ptrThis.element, provided that you have an iteration where ptrParam moves along the parameter list.
There is no return statement after the for loop...
You need a counter to address the requirement that a match must occur at least twice.
Here is some code you could use:
class MyLinkedList {
public MyLinkedList appearsTwice(MyLinkedList paramList) {
MyLinkedList<E> returnList = new MyLinkedList<E>();
if (paramList.head == null) return returnList; // shortcut
for (Node<E> ptrParam = paramList.head; ptrParam != null; ptrParam = ptrParam.next) {
// For each node in the param list, count the number of occurrences,
// starting from 0
int count = 0;
for (Node<E> ptrThis = head; ptrThis != null; ptrThis = ptrThis.next) {
// compare elements from both nodes
if (ptrThis.element == ptrParam.element) {
count++;
if (count >= 2) {
returnList.append(ptrParam.element);
// no need to look further in the calling list
// for this param element
break;
}
}
}
}
return returnList; // always return the return list
}
}

Adding to SortedLinkedList using nodes

im making a SortedLinkedList, I'm trying to add lets say 10 integers of different value so I can run some asssert tests. But I'm having a problem adding them so they are already sorted when they arrive to the LinkedList, I tried using the curr.info.compareTo(x) > 0 for instance, but I'm having trouble making the correct else/if statements so it sorts them when they are added.
This code has 4 classes, I can provide more if its unclear.
Thank you for your help in advance.
Best regards,
Victor
public class SortedLinkedList<T extends Comparable<T>> implements Iterable<T> {
/* Easy operations for a linked list
add(x): Searching for the place where the element x is to be added must
take place in the calling routine. This must set previous to
point to the node AFTER which the new element is to be inserted.
curr is set to point to the new element.
remove(): The curr element is removed from the list. Searching for this
element must take place in the calling routine. This must set
curr to point to the element to be removed. After removal curr
points to the element following the removed one.
isEmpty(): checks for an empty list
endOfList(): checks whether curr has reached and passed the end of the list
retrievecurr(): return the info part of the curr element.
reset(): resets the list so that curr points to the first element
succ(): an iterator, moves curr one step forward
Note that when a class implements the interface Iterable<T> then
it can be the target of the "foreach" statement. See IterationExample.java */
private Node start, curr, prev;
public SortedLinkedList() {
curr = null; // the curr position in the list
start = null; // the first element
prev = null; // the node before curr
}
public void add(T x) {
if (start == null) { // if start == null, insert a first element into an empty list
Node newNode = new Node(); // create the new element, info and link are set to null.
newNode.info = x; // and assign the data given as parameter. The link is left as null
start = newNode; // start is updated to point to the new element
curr = start; // curr is updated to point to the new first (and only) element
} else if (prev == null) { // a new first element is inserterd into a non-empty list
Node newNode = new Node(); // a new node is created ...
newNode.info = x; // and assigned the data given as parameter
newNode.link = start; // and linked before the old first element
start = newNode; // start is updated to point to the new first element
curr = newNode; // curr is updated to point to the new first element
} else { // a new element is inserted last (if prev.link == null) or between prev and curr
Node newNode = new Node(); // create a new node
newNode.info = x; // assign it the data given as parameter
newNode.link = prev.link; // link it before curr ...
prev.link = newNode; // ... and after previous
curr = newNode; // update curr to point to newNode
}
} // add*
}

Big-O for while loop?

How do I solve the Big-O for this problem containing a while loop that goes through the nodes and increment the length as long as it does not equal to null? Would this just be O(N) because it goes through N nodes? Also, the statements within the while loop would just be O(1), correct?
/**
*#param head the first node of the linked list
*#return the length of the linked list
*/
public static <E> int getLength(Node<E> head) {
int length = 0;
Node<E> node = head;
while (node!=null) {
length++;
node = node.next;
}
return length;
}
As you said the traversal of a linked list takes O(N) since you need to go over each node once.
The assignment operator is O(1), since you need to do this just once, every time.

Out of Memory using Java API but Cypher query can work although it is slow

I have a graph database with 150 million nodes and a few hundred million relationships.
There are two types of nodes in the network: account node and transaction node. Each account node has a public key and each transaction node has a number (the amount of total bitcoin involved in this transaction).
There are also two types of relationships in the network. Each relationship connects an account node with a transaction node. One type of relationships is "send" and the other type is "receive". Each relationship also has a number to represent how much bitcoin it sends or receives.
This is an example:
(account: publickey = A)-[send: bitcoin=1.0]->(transaction :id = 1, Tbitcoin=1.0)-[receive: bitcoin=0.5]->(account: publickey = B)
(account: publickey = A)-[send: bitcoin=1.0]->(transaction :id = 1, Tbitcoin=1.0)-[receive: bitcoin=0.5]->(account: publickey = C)
As you can imagine, B or C can also send or receive bitcoins to or from other accounts which involves many different transactions.
What I wants to do is to find all paths with depth equaling to 4 between two accounts, e.g. A and C. I can do this by Cypher although it is slow. It takes about 20mins. My cypher is like this:
start src=node:keys(PublicKey="A"),dest=node:keys(PublicKey="C")
match p=src-->(t1)-->(r1)-->(t2)-->dest
return count(p);
However, when I try to do that using Java API, I got the OutOfMemoryError. Here is my function:
public ArrayList<Path> getPathsWithConditionsBetweenNodes(String indexName, String sfieldName, String sValue1, String sValue2,
int depth, final double threshold, String relType){
ArrayList<Path> res = null;
if (isIndexExistforNode(indexName)) {
try (Transaction tx = graphDB.beginTx()) {
IndexManager index = graphDB.index();
Index<Node> accounts = index.forNodes(indexName);
IndexHits<Node> hits = null;
hits = accounts.get(sfieldName, sValue1);
Node src = null, dest = null;
if(hits.iterator().hasNext())
src = hits.iterator().next();
hits = null;
hits = accounts.get(sfieldName, sValue2);
if(hits.iterator().hasNext())
dest = hits.iterator().next();
if(src==null || dest==null){
System.out.println("Either src or dest node is not avaialble.");
}
TraversalDescription td = graphDB.traversalDescription()
.depthFirst();
if (relType.equalsIgnoreCase("send")) {
td = td.relationships(Rels.Send, Direction.OUTGOING);
td = td.relationships(Rels.Receive, Direction.OUTGOING);
} else if (relType.equalsIgnoreCase("receive")) {
td= td.relationships(Rels.Receive,Direction.INCOMING);
td = td.relationships(Rels.Send,Direction.INCOMING);
} else {
System.out
.println("Traverse Without Type Constrain Because Unknown Relationship Type is Provided to The Function.");
}
td = td.evaluator(Evaluators.includingDepths(depth, depth))
.uniqueness(Uniqueness.RELATIONSHIP_PATH)
.evaluator(Evaluators.returnWhereEndNodeIs(dest));
td = td.evaluator(new Evaluator() {
#Override
public Evaluation evaluate(Path path) {
if (path.length() == 0) {
return Evaluation.EXCLUDE_AND_CONTINUE;
} else {
Node node = path.endNode();
if (!node.hasProperty("TBitcoin"))
return Evaluation.INCLUDE_AND_CONTINUE;
double coin = (double) node.getProperty("TBitcoin");
if (threshold!=Double.MIN_VALUE) {
if (coin<=threshold) {
return Evaluation.EXCLUDE_AND_PRUNE;
} else {
return Evaluation.INCLUDE_AND_CONTINUE;
}
} else {
return Evaluation.INCLUDE_AND_CONTINUE;
}
}
}
});
res = new ArrayList<Path>();
int i=0;
for(Path path : td.traverse(src)){
i++;
//System.out.println(path);
//res.add(path);
}
System.out.println();
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
} else {
;
}
return res;
}
Can someone take a look at my function and give me some ideas why it is so slow and will cause out-of-memory error? I set Xmx=15000m while runing this program.
My $0.02 is that you shouldn't do this with java, you should do it with Cypher. But your query needs some work. Here's your basic query:
start src=node:keys(PublicKey="A"),dest=node:keys(PublicKey="C")
match p=src-->(t1)-->(r1)-->(t2)-->dest
return count(p);
There are at least two problems with this:
The intermediate r1 could be the same as your original src, or your original dest (which probably isn't what you want, you're looking for intermediaries)
You don't specify that t1 or t2 are send or receive. Meaning that you're forcing cypher to match both kinds of edges. Meaning cypher has to look through a lot more stuff to give you your answer.
Here's how to tighten your query so it should perform much better:
start src=node:keys(PublicKey="A"),dest=node:keys(PublicKey="C")
match p=src-[:send]->(t1:transaction)-[:receive]->(r1)-[:send]->(t2:transaction)-[:receive]->dest
where r1 <> src and
r1 <> dest
return count(p);
This should prune out a lot of possible edge and node traversals that you're currently doing, that you don't need to be doing.
If I have understood what you are trying to achieve and because you have a direction on your relationship I think that you can get away with something quite simple:
MATCH (src:keys{publickey:'A')-[r:SEND|RECEIVE*4]->(dest:keys{publickey:'C'})
RETURN COUNT(r)
Depending on your data set #FrobberOfBits makes a good point regarding testing equality of intermediaries which you cannot do using this approach, however with just the two transactions you are testing for cases where a Transaction source and destination are the same (r1 <> src and r1 <> dest), which may not even be valid in your model. If you were testing 3 or more transactions then things would get more interesting as you might want to exclude paths like (A)-->(T1)-->(B)-->(T2)-->(A)-->(T3)-->(C)
Shameless theft:
MATCH path=(src:keys{publickey:'A')-[r:SEND|RECEIVE*6]->(dest:keys{publickey:'C'})
WHERE ALL (n IN NODES(path)
WHERE (1=LENGTH(FILTER(m IN NODES(path)
WHERE m=n))))
RETURN COUNT(path)
Or traversal (caveat, pseudo code, never used it):
PathExpander expander = PathExapnder.forTypesAndDirections("SEND", OUTGOING, "RECEIVE", OUTGOING)
PathFinder<Path> finder = GraphAlgoFactory.allSimplePaths(expander, 6);
Iterable<Path> paths = finder.findAllPaths(src, dest);

How do I join two linked lists in C?

I'm wanting to complete two linked lists in preparation for an exam
here is what I have so far
1 - reverse the elements in a linked list
2 - append list2 to the end of list one
I got help with the reverse function off someone in my course and have tried to comment out each step to understand what is going on but I am struggling. If you could also help me out with that it would be fantasticcaalll
In the combine function I am just confused overall
When do I use '&' and when do I use '*'?
typedef struct node *list;
typedef struct node {
int value;
list whateverNextIsCalled;
} node;
// Reverse list
list reverse (list inputList){
list outputList = NULL;
while (inputList != NULL) {
/*
nodePtr points to the first element in the inputList
*/
node *nodePtr = inputList;
/*
Make the head pointer of inputList point to the next element
*/
inputList = inputList->whateverNextIsCalled;
/*
???? help point 1
*/
nodePtr->whateverNextIsCalled = outputList;
/*
???? help point 2
*/
outputList = nodePtr;
}
return outputList;
}
// Add one list to the end of another
void combine (list list1, list list2){
/*
Point to the first value of list1
*/
node *current = list1;
/*
Find the last node of list1
*/
while(current->whateverNextIsCalled != NULL) {
current = current->whateverNextIsCalled;
}
//connect the last node of toList and the first node of fromList
current->whateverNextIsCalled = &list2;
list1 = current;
}
you can just reach to the last of the first linked list and in its next where there will be null just put the start of next linked list
i dint understand why you have reversed the list

Resources