JNA initialization of empty node structures - java

I have node structure (it contain value on next same structure).
struct Node {
Node *nextElem;
Element thisValue;
};
I want to pass empty (null) node.ByReference in function that fills it.
// C++
Element element = ...; //fills in another function;
Node *list = NULL;
AddElementToList(element, &list);
// which declered as
void AddElementToList (Element element, Node * list) {...}
// Java
Element.ByValue element = ...; //fills great in another function in the same way ByReference (and reconstructed as ByValue),
//but initialize with trash in Pointers and without recurtion;
Node.ByReference list = null;
MyDll.INSTANCE.AddElementToList(element, list);
So if I use
Node.ByReference list = null;
I get Invalid memory access Error when C++ side try to read list, like for any null Pointers.
So I'm trying initialize list. But in that case I have to init next node and next and...

I find out solution by wrapping Node in PointerByReference:
// method declaration:
void AddElementToList(Element element, PointerByReference wrapedNodeInPointerByRef);
Usage:
Element.ByValue element = ...;
PointerByReference list = new PointerByReference();
MyDll.INSTANCE.AddElementToList(element, list); // yes, Element.ByValue puts in Element
// but to get **Node** from filled PointerByReference you should reparse it like:
Node node = new Node(list.getValue());
For that create constructor:
public Node (Pointer value) {
super(value);
read();
}
Constructors for Node.ByValue and Node.ByReference I have get in same way.
This example is simplified version from complicated program with more abstractions, but hope nothing was lost and will helpful for somebody.
Some thinkings:
If PointerByReference can has empty instanse, whether Structure.ByReference's can't?
Not clear why Element.ByValue works like Element, but when declaration with Element.ByValue it couses to Invalid memory access.

Related

Reversing a linked list in Java without changing the original

I am trying to reverse a linked list which works, but when I try to print the original, it fails (only prints the head). My question is, why would reversing affect the original. Below is my code. LinkedList is my own class, so is Node. Before reversing, if I try to print my list, that works.
public static void main(String[] args) {
LinkedList list;
...
Node head = list.getHead();
Node rev = reverse(head);
Node temp = rev;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
temp = head;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
private static reverse(Node head) {
// Reversing the linked list
}
EDIT::
This seems to be a Java thing. Java passes an object by reference. When I pass head as a parameter, it's passed by reference and any change made to it is reflected in the calling function.
Doing Node h = head and then passing h as a parameter won't work either since h will be the same object as head.
The only option I can think of is to create a new object, copy the linked list over and pass that as a parameter.
My question becomes, is there a better solution?
To understand it, picture your list looks like this
list (list.head =a) --> a (a.next=b) --> b (b.next= c) -> c (c.next = null)
If you get the head, then you are getting object 'a'.
Then you are modifying object 'a'.
So you can see you are editing the list by doing this.
What you need to do is:
Get the head
Create a copy
Reverse the copy
Get the next item
Copy it
Reverse it
Join it to the last
And so on
Since you are using your own classes not java collections classes, the easiest way is for you to make sure that reverseNode() only edits a copy of the one you pass it, and returns the copy.
First make sure your Node class has a constructor that copies another Node, then do something like this:
private static Node reverse(Node original)
{
Node retval = new Node(original);
// or you could use clone () as Bhavik suggested, if your Node class implements it
// modify retval
// I haven't shown code to reverse it as I assume you already have that and you didnt specify if it was a bidirectional list or just one direction.
return retval;
}
Or you might add a static method in your Node class that constructs a new node that is reversed:
static Node createReverse(Node n)
{
return new Node(n.data,n.next,n.prior);
}
Or a non static method of the node class which returns a reversed copy of itself;
Node createReverse()
{
return new Node(this.data,this.next,this.prior);
}
But you should consider this can get very ugly because your copies will still have pointers pointing into the existing list!
A better technique might be to create a new empty list, and then start from the end of your original, make a copy, and add it to the start of your new list.
You can use recursion to do this but might easily run out of memory.
But rather than do this manually, you might look at the java.util packages and switch to using one of their LinkedList and list item types. These classes have already solved all the problems with doing this stuff.
Then you could (if you need to keep the original list unmodified):
- Make a copy of your entire list.
- reverse the copy as below
If you don't care about keeping the original, then just use this method(below) on your list, no need then to make a copy.
From java.util.Collections:
Collections.reverse(List a_list);
The Collections class will choose an efficient way to reverse the list, depending on whether it is bidirectional, single directional, etc.
Chunko's answer is right in that you should be creating copies of your Nodes instead of just passing references to them.
However, I think you might be overthinking this:
LinkedList reversedList = new LinkedList();
for (int i = originalList.size()-1; i >= 0; i--) {
reversedList.add(list.get(i));
}
Java's LinkedList doesn't have a getHead() method, so I guess you're using some homework-related custom implementation of a linked list. Still, your implementation should have an add() method that appends a new Node to the list, as well as a get(int) method that returns the item in a given position.
You can use those methods to create a new list and populate it with the original list's items in reversed order.

duplicating a node in a linked list java

just to start off, this is homework and thank you for your assistance ahead of time. I keep getting stuck on little problems so I am hoping you guys can help me with one. What I am trying to do is create a linked list that has multiples functions. The one I am having trouble with is sorting(I can do the other ones). Each node holds a string, an integer and a double. I need to be able to sort by each of these and by the order it was inputted, on the user's request. ***It is also important to mention that the variables in my object are private and my object is called list1. Basically, I have to make one linked list for the chronological order and one for each other order.
My plan is to insert the nodes in their correct order as the user inputs them. So as the user inputs a node, that node needs to go in the correct place in the chronological list and in the other lists. So, I need to copy the node to do this. However, I cannot simply just say
icopy(copy for integer) = newNode(node the user just inputted)
That only changes the address. When I went to my instructor he told me that I should say:
icopy.data = newNode.data;
("data" being the shortcut way of mentioning that I need to get the individual data types within the node.) So I wrote:
icopy.GetI() = newNode.GetI();
When I do this I encounter this error: unexpected type required:variable, found:value. I am not sure what to do. Any assistance would be appreciated and I would be happy to clarify anything.
*GetI: method in my object that gives access to the integer value in each node.
*p: pointer for the Chronological
*pi: pointer for the integer.
*fi: front of the integer linked list
public static void main(String args[])
{
String repeat = "y";
boolean inserted = false;
list1 fChr = null;
list1 p = fChr;
list1 icopy = null;
list1 scopy = null;
list1 dcopy = null;
list1 fd = fChr;//front of the double list
list1 fi = null;//front of the integer list
list1 fStr = fChr;//front of the string list~
while(repeat.equals("y"))//while the user agrees to adding a new node
{
if(fChr == null)// if the front is empty
{
fChr = new list1();//create a new node by calling object and sets it as the front
}
else
{
p = fChr;
while(p.next != null)//finds the end of the Linked list
{
p = p.next;//moves the pointer p down the list
}
list1 newNode = new list1();
icopy.GetI() = newNode.GetI();// make a copy of newNode
p.next = nexNode;//put in chronological order
while(p != null)
{
if(fi == null)
{
fi = n;
}
else if(n.GetI() < fi.GetI)//check at beginning
{
//put at beginning
}
else if(icopy.GetI() < p.next.GetI())//check in between nodes
{
//put in between
}
//does it go at the end
}
}
repeat = JOptionPane.showInputDialog("Would you like to add a node [y/n]");
}
PrintMenu(fChr, fi, fd, fStr);// sends the user to the menu screen
}
There are a few things here that you are not understanding. Firstly, in Java iCopy.getI() = ... makes no sense. When a method returns a value it needs to be assigned to a variable if you wish to change it. If you want to change the instance variable you need a separate method called something like iCopy.setI().
It sounds as though you're not asking for help with the sorting so I'll restrict my answer to creating copies of the list.
What your professor is getting at is that the easiest way to ensure the data is consistent in your several linked lists is to separate the class storing the data from the nodes of the list. So I would expect your class structure to end up looking something like:
class Data {
private final int intValue;
private final String strValue;
private final double doubleValue;
}
class Node {
private final Data data;
private Node next;
public Node(Data data) {
this.data = data;
this.next = null;
}
}
Now if you want to create a new linked list with the same data as the old one then you can add a constructor to Node that creates a reference to the original data:
class Node {
public Node copy() {
Node copy = new Node(data);
if (next != null)
copy.next = next.copy();
return copy;
}
}
Hopefully you can see what that does: it creates a new node referencing the same data as this one and then uses recursion to copy the rest of the list.
Now creating each of the sort orders could look like:
Node listByInt = list.copy();
/* code to sort listByInt according to data.intValue */
Add a comment if you want some hints on sorting as well but I suggest you get your code to the point of having equal copies of lists before attempting that.
As a final note, you don't necessarily need to have separate linked lists to solve this problem. An alternative would be to store the original insertion order in the node. You could then sort by any order (including original insertion order) before printing the list. Personally I'd prefer that as a solution unless there are performance issues (e.g. you need to use each sorted list many times).

Java ArrayList and LinkedList - adding element at end implementation details

My understanding of why arraylist is faster than a linkedlist is that with an arraylist you basically only need one action - update the reference at the end array element, whereas with a linked list you have to do much more e.g. create a new node, update 2 references, go through linked list and update the last node to point to the new one etc.
However I am not sure how java implement these. How does the arraylist know where the "last" element is, does it store a value of the last element or does it traverse the array and add a new element after the last?
And linked lists, do they store a reference to the last node in the list, or do they traverse the entire list to get to the end?
Look at the source:
ArrayList:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
LinkedList:
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
An array-list is only faster at certain operations. If you add an element in the middle of an array the arraylist needs to copy basically all data into a new array. It is only if the arraylist already have allocated room for new data it is fast when inserting data where it is empty (usually in the end). Read/update by index is very-fast.
A LinkedList is fast when inserting since it never require the whole array to be copied. But accessing data in a linked list is slow since you need to "walk" all the elements until you are at the element you want to find.
You can always look at the sources of java.* classes.
However, answering particular your question: there is int field in ArrayList class, which contains current size of filled internal array area. When you add new value in ArrayList object, this field increments and then directly addresses to that element in internal array.

How to duplicate a linked list in java?

My Node class, representing a node of a linked list, is defined like this:
public class Node
{
Node next;
String data;
public Node (String data)
{
this.data = data;
}
}
and I'm using it like this:
Node node, head, tail;
String name; // name to be entered
int count = 0;
// initialize the head to null
head = null;
do
{
System.out.print ("Enter a name. Type q to end.");
name = stdin.readLine ();
// create a new node if the user doesn't type q
if (!name.equals ("q"))
{
node = new Node (name);
node.next = head;
count++;
// update the head to point to the new front of the list
head = node;
}
}
while (!name.equals ("q")); // loop continues until "quit" selected
node = head;
Suppose I wanted to back the names up to a method in case I modify the original list. How can I do this? Without writing it to a file.
Name is the variable that gets stored in the linked list and after the user presses q I want to modify the list while keeping what the user stored as a back up in case he/she wants to backtrack or see the original list.
It would be better to make the Node immutable. So every time when you want to modify the node, you create a new node. And store the old one in the linklist history.
So it sounds as though you want to keep a history of the prior names for each element in the linked list. I would suggest that you store an array or linked list within each node of the linked list that shows the prior history of that item. For instance:
public class Node
{
Node next;
String data;
LinkedList<String> history;
public Node (String data)
{
this.data = data;
}
}
You could populate this in many ways, that all really depend upon your use case.
Also, why implement your own linked list? Java already comes with a linked list implementation (java.util.LinkedList). I'd suggest using this if you need an ordered list of the linked list variety. If you did this, then create a new data structure to be contained within it that has a name and history, then just maintain the history within that, such as:
public class DataItem
{
String data;
LinkedList<String> history = new LinkedList<>();
public DataItem (String data)
{
this.data = data;
}
public void setData (String data)
{
this.history.add(0, this.data);
this.data = data;
}
}
Ultimately, remember that strings are immutable in Java. So, a string cannot be modified. You only need to keep a reference to the prior string somewhere, you don't need to copy the value.
To ultimately copy a tree of objects, you need to do what's called a deep copy, basically going through the full structure and all collections, and cloning each object into a new object.

Deep Copying in Java

I have a Java class, Node as follows :
class Node
{
public ArrayList<Node> nbrs;
}
Each Node object contains a list of all its neighbours within the ArrayList nbrs, and nothing else.
Now I need to write a function :
public Node copy( Node curr )
This function should perform a deep copy of the entire graph rooted at curr, and return the equivalent copy for curr.
I tried implementing a copy constructor within the class Node as follows :
public Node( Node n )
{
for( Node curr : n.nbrs )
n.nbrs.add( new Node( curr ));
}
I now copy the Node n, within my copy function.
But I have found that when the graph contains loops, this code keeps running infinitely.
Any help on how I should overcome this problem.
PS : This is an interview question faced by my friend, so the class Node cannot contain any more variables
If the Node class had a parent you'd be able to check for infinite recursion that way. But it doesn't. So you'll need to maintain some state during the clone operation, a Set containing the nodes you are currently recursing into. Refuse to descend into a node that is already in the Set.
Save the mapping between the old nodes being copied and the new ones in a data structure that allows retrieving elements based on identity (i.e. that retrieves objects iff the == operator returns true). An example for this would be the IdentityHashMap. If you create a new node, then save it to the data structure.
Before creating a new Node from a previous ony, try to retrieve the node from the data structure. If you have such a node already, then add the retrieved one to the parent. If you don't have such a node, then continue creating one (and add it).
The standard trick is to first create all the new nodes and store them in a map (from old nodes to new nodes). Then in a second pass over all the nodes, all the edges are added (by adding to n.nbrs.add).
Consider making Node objects immutable. In this case using shared instance will do no harm.
If you can modify the Node class and make it Serializable, then you serialize/deserialize the object and get a new graph of objects.
Sample code to illustrate the point:
class Node implements Serializable
{
public List<Node> nbrs = new ArrayList<Node>();
}
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
n1.nbrs.add(n2);
n2.nbrs.add(n1);
n2.nbrs.add(n3);
n3.nbrs.add(n2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream dos = new ObjectOutputStream(baos);
dos.writeObject(n1);
dos.writeObject(n2);
dos.writeObject(n3);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Node n4 = (Node) ois.readObject();
Node n5 = (Node) ois.readObject();
Node n6 = (Node) ois.readObject();
At this stage, you'll have a new set of Node objects, which correctly reference each other.
There is no base case in the recursion, other than a node with no neighbors.
Daniel Earwicker suggested using a Set to make sure we don't add the same neighbor twice. Sounds good, but how can we tell if a node is in the Set? The default implementation of equals is really just == so no two nodes would be considered equal. The Set contains method relies on equals to determine if an object has already been added to a set. We cold add an id field to the node and then implement boolean equals(Node other) by checking for id equality. That should make the Set solution work.

Categories

Resources