How to get the position of an Element in the childNode list?
e.g.
<a>
<b></b><!-- return 0 -->
<c></c><!-- return 1 -->
</a>
I don't think Element, Node, or NodeList provide a direct way to get this info, but it's easy enough to write your own quick function to do it:
int indexOfNode(Node node) {
int index;
Node sibling;
index = 0;
while ((sibling = node.getPreviousSibling()) != null) {
node = sibling;
++index;
}
return index;
}
I don't think there's a straightforward way other than to repeatedly call getPreviousSibling() until it returns null or iterate through the parent node's child list until you find one that is == to the node you started with.
As an aside, in the document you give in the question the b element is index 1 in its parent's list of children, and the c element is index 3, because there are whitespace-only text nodes in between (one between the opening a and opening b and another between the closing b and opening c).
Related
Hi I have a tree in which I would like to get paths from the initial (root) node to all leaves.
I found several algortithms that list (all) apths betwenn any given two nodes within a graph (for example this SO question:
Graph Algorithm To Find All Connections Between Two Arbitrary Vertices)
For binary tree there also exists an algorithm
http://techieme.in/print-all-paths-in-a-tree/
but I work on a tree with various branching factors.
Is there any better way of achieving what I want to do than traversing the tree once in order to get all leaves and then run the algorithm above for all leaves combined with the initial node?
I was thinking about implementing simple DFS extended by some additional stack containing all nodes alongt he path to a single leaf and then listing all sentences by looping through these stacks.
ArrayList<GrammarNode> discovered = new ArrayList<GrammarNode>();
Stack<GrammarNode> S = new Stack<GrammarNode>();
while (!S.empty()) {
node = S.pop();
if (!discovered.contains(node)) {
discovered.add(node);
System.out.println(node.getWord.getSpelling().trim());
for (GrammarArc arc : node.getSuccessors()) {
S.push(arc.getGrammarNode());
}
}
}
UPDATE:
The problem of this is that one has alyways go back to the root in order to generate full sentences. So I guess the question is: How to remember the node which was already fully visited (this means where all children nodes were already explored)?
Printing all paths from the root to every leaf would mean to print the entire tree so I'd just use a simple DFS and do the following for each node:
add it to the list/stack
if the node has children, repeat for the children
if the node is a leaf, print the list/stack
pop the node from the list/stack
Example:
A
/ \
B E
/ \ / \
C D F G
The first steps would look like this:
put A on the list -> {A}
put B on the list -> {A,B}
put C on the list -> {A,B,C}
since C is a leaf, print the list (A,B,C)
remove C from the list -> {A,B}
put D on the list -> {A,B,D}
since D is a leaf, print the list (A,B,D)
...
if you know that the graph is indeed a tree (there is only one path to each node), them yes, a simple DFS would be more efficient (at least from a memory usage point of view). Otherwise, you can also use the iterative deepening DFS.
So here's a sample approach. Note that you need an extra visited field in your node structure:
public class TreeNodeExtra {
int val;
TreeNodeExtra left;
TreeNodeExtra right;
boolean visited;
TreeNodeExtra (int v) {
val = v;
visited = false;
}
}
private ArrayList<ArrayList<TreeNodeExtra>> all_path_from_root_to_leaf(TreeNodeExtra root) {
Stack<TreeNodeExtra> st = new Stack<>();
ArrayList<ArrayList<TreeNodeExtra>> res = new ArrayList<>();
st.push(root);
root.visited = true;
while (!st.isEmpty()) {
TreeNodeExtra top = st.peek();
if (top.left != null && !top.left.visited) {
st.push(top.left);
top.left.visited = true;
}
// if left node is null
else {
if (top.right == null && top.left == null) {
// we have a leaf
ArrayList<TreeNodeExtra> tmpList = new ArrayList<>();
for (TreeNodeExtra t : st) {
tmpList.add(t);
}
res.add(tmpList);
st.pop();
}
else if (top.right != null && !top.right.visited) {
st.push(top.right);
top.right.visited = true;
}
else {
st.pop();
}
}
}
return res;
}
A slight modification of DFS (which includes back-tracking) prints all the paths from a given source. In the below example the graph is represented in adjacency list format.
public void mDFS(ArrayList<node> v,int ind,ArrayList<Boolean> visit,ArrayList<node> tillNow){
visit.set(ind,true);
node n = v.get(ind);
int len = n.adj.size();
tillNow.add(n);
int count = 0;
for(node tmp: n.adj){
if( !visit.get(tmp.id) ){
count++;
tmp.pre = ind;
mDFS(v,tmp.id,visit,tillNow); // id gives index of node in v
}
}
if(count == 0){
for(node tmp: tillNow){
System.out.print((tmp.id + 1) + " - ");
}System.out.print("\n");
}
visit.set(ind,false);
tillNow.remove(tillNow.size() - 1);
return;
}
I am tring to insert string into doubly linked list in reverse order. But I am not sure how can I maintain the insertion order in reverse order.
This is my below code.
theList.insertReverseLexicographicalOrder("B");
theList.insertReverseLexicographicalOrder("A");
theList.insertReverseLexicographicalOrder("H");
theList.insertReverseLexicographicalOrder("D");
theList.insertReverseLexicographicalOrder("E");
public void insertReverseLexicographicalOrder(String dd) {
Link newLink = new Link(dd);
if (isEmpty()){
last = newLink;
}
first.previous = newLink;
}
newLink.next = first;
first = newLink;
}
Any suggestions will be appreciated with some code based on my solution..
Well you assume that its already in reverse order, so you're going to need some sort of loop through until you find where it should go.. i.e.
Z, Y, X, W, L, K, A
if you're inserting M, then you should loop until you find L, which is lexicographically larger than M, and therefore insert it there. Because the nodes have previous pointers, insertion shouldn't be too hard to figure out on your own
You would need to look through the list comparing each of the elements. Stop when you find the element that goes after the element you are trying to insert. I suggest you implement the compareTo method in your node class: http://www.javapractices.com/topic/TopicAction.do?Id=10
and use it to make the comparisons
Good Luck.
How to insert a node into a linked list:
If the list is empty, the new node will become the first, and if we keep track of that, also the last
Otherwise find the position where to insert, there are three possibilities,
a) the new node has to be inserted before the first
b) the new node has to be inserted after the last
c) the new node has to be inserted between two existing nodes
Update the appropriate references, that may be first, last and some next and previous fields, depending on where it has to be inserted
if (first == null) {
// the list is empty so far
} else
To find the position, first compare the data with the first node's data to see whether it has to be inserted before the first node.
if (newLink.iData.compareTo(first.iData) > 0) {
// put newLink before first
} else {
You have to keep a focus on some list node. Follow the list from the start until you reach the point of insertion:
Link focus = first; // focus first node
while(focus.next != null && newLink.iData.compareTo(focus.next.iData) < 0) {
focus = focus.next;
}
// now you have to insert the new value behind focus, left as exercise
if (focus.next == null) {
// newLink becomes the last node in the list
} else {
// newLink has to be inserted between focus and focus.next
}
}
Then insert. Beware of edge cases, inserting at the front and the end are slightly different.
I need to find the number of elements in a tree using an iterative algorithm, but I'm finding the code conceptually very difficult to write.
My approach is to start at the root node and visit the child nodes, then the children of these child nodes, and so on.
This is the code I've written which works for a small tree, but isn't a real solution because I'd need to add an additional block for each level of depth:
// Start the counter at 1 because the root node counts
int size = 1;
for(ITree child1 : root) {
size++;
for(ITree child2 : child1) {
size++;
for(ITree child3 : child2) {
size++;
for(ITree child4 : child3) {
size++;
for(ITree child5 : child4) {
size++;
}
}
}
}
}
return size;
Conceptually, keep a stack (LinkedList, etc.). For each child (now, your child loops), add to the stack. Continue looping through the stack until it is finally empty.
This isn't tested, but this should do exactly what you're looking for. I'm just using java.io.File instead of your "ITree", as it's something I can compile against:
int sizeOfTree(File root){
// Start the counter at 1 because the root node counts
int size = 1;
LinkedList<File> stack = new LinkedList<File>();
stack.add(root);
while(!stack.isEmpty()){
File f = stack.remove();
for(File child : f.listFiles()){
size++;
stack.add(child);
}
}
return size;
}
Using a recursive data structure
It is not practically possible to iteratively traverse a recursive data structure, like a tree with pointers - this is because of the fact that the objects "hide" their underlying data elements.
Using a different data structure
All trees can be stored/implemented as to linear, array data structures, where indices can be calculated using exponential mathematics :
For example, a tree [0, 1, 2, 3, null, 4,null] would describe a tree with 0 at the root, where 0 had direct children 1 and 2. And then 1 has left child "3", and 2 has left child "4".
Thus, if you store the tree this way, the number of elements is, naturally, the number of non-null elements in the array.
Put more simply : Store the tree in a linear structure , and you can know the length at any given time without having to make any kind of fancy algorithm.
The key word for your task is recursion. Tree is a classical recursive structure, so you should write recursive method that accepts root nodes, counts size of this node and then calls itself for all children. Here is pseudo code:
public int getSize(ITree root) {
return getSize(root, 0);
}
private int getSize(ITree node, int size) {
size++;
for(ITree child : node.children()) {
size += getSize(child, size)
}
return size;
}
It's for a school assignment. I have to use a search method that returns the node that I search for or the one right before it if it doesn't exist. Obviously if I want to delete a node it'll return that one node and I won't be able to find the one that comes before it. Here's the code for the search method:
private myNode search(myEntry searchEntry)
{
myNode ref = first;
myNode pre = null;
while(ref != null)
{
if(searchEntry.compareTo(ref.data) < 0)
break;
pre = ref;
ref = ref.link;
}
return pre;
}
first is the first node, ref is the pointer, pre is the node preceding the pointer.
Maybe I'll use a doubly-linked list if it doesn't require me to rewrite things too much but if there's a simple way to find the predecessor of the node I'm trying to delete using this search method then I'd like to know. I'm not supposed to be using doubly-linked lists at all.
You can't do that with your search method. You have to implement a distinct search method that return the predecessor of the node and then delete it.
If you need to delete ref, than you return pre. To delete ref, you can write something like
pre = list.search(entry); //find the prescending node
ref = pre.link; //get the node you want to delete
pre.link = ref.link; //reassign link
ref.delete(); //delete node
Given the current node, how can I find its previous node in a Singly Linked List. Thanks. Logic will do , code is appreciated. We all know given a root node one can do a sequential traverse , I want to know if there is a smarter way that avoids sequential access overhead. (assume there is no access to root node) Thanks.
You can't.
Singly-linked lists by definition only link each node to its successor, not predecessor. There is no information about the predecessor; not even information about whether it exists at all (your node could be the head of the list).
You could use a doubly-linked list.
You could try to rearrange everything so you have the predecessor passed in as a parameter in the first place.
You could scan the entire heap looking for a record that looks like a predecessor node with a pointer to your node. (Not a serious suggestion.)
If you want to delete the current node, you can do that without finding previous node as well.
Python Code:
def deleteNode(self, node):
node.val = node.next.val
node.next = node.next.next
# Delete Node in a Linked List
Walk through the list from the beginning until you meet a node whose next link points you your current node.
But if you need to do this, perhaps you oughtn't be using a singly linked list in the first place.
Your only option for a singly-linked list is a linear search, something like below (Python-like pseudo code):
find_previous_node(list, node):
current_node = list.first
while(current_node.next != null):
if(current_node.next == node):
return current_node
else:
current_node = current_node.next
return null
Assuming that you're talking about a forward singly linked list (each node only has a pointer to 'next' etc) you will have to iterate from the start of the list until you find the node that has 'next' equal to your current node. Obviously, this is a slow O(n) operation.
Hope this helps.
Keep two-pointer(curr, prev) initially both will point to head of the list.
do a loop on the list until you either reach at the end of the list or at the required node.
for each iteration move curr node to the next of it but before moving to next store its pointer in prev pointer.
prev = curr; // first store current node in prev
curr = curr->next // move current to next
at the end of loop prev node will contain previous node.
getPrev(head, key) {
Node* curr = head;
Node* prev = head;
while(curr !=null && curr->data==key){
prev = curr;
curr = curr->next
}
return prev
}
Example:
list = 1->5->10->4->3
We want prev node of 4 So key = 4 and head point at 1 here
initially:
temp will point to 1
prev will point to 1
iteration 1:
First, assign prev=temp (prev point to 1)
move temp; temp->next (temp point to 5)
iteration 2:
First, assign prev=temp (prev point to 5)
move temp; temp->next (temp point to 10)
iteration 3:
First, assign prev=temp (prev point to 10)
move temp; temp->next (temp point to 4)
iteration 4:
temp->data == key so it will return out of loop.
return prev node
This is some kind of hack which I found out while solving the problem(Delete every even node in a list)
internal void DeleteNode(int p)
{
DeleteNode(head, p);
}
private void DeleteNode(Node head, int p)
{
Node current = head;
Node prev = null;
while (current.next != null)
{
prev = current;
current = current.next;
if (current.data == p)
{
prev.next = current.next;
}
}
}
Now here, in prev you assign the current and then move the current to next thereby prev contains the previous node.
Hope this helps...
You can do it like this.. you can replace the value of current node by value of next node.. and in the next of 2nd last node you can put null. its like delete a element from a string. here is code
void deleteNode(ListNode* node) {
ListNode *pre=node;
while(node->next)
{
node->val=node->next->val;
pre=node;
node=node->next;
}
pre->next=NULL;
}
Use a nodeAt() method and pass the head,size and the index of the current node.
public static Node nodeAt(Node head,int index){
Node n=head;
for(int i=0;i<index;i++,n=n.next)
;
return n;
}
where n returns the node of the predecessor.
Here is a small trick with linear search: just pass in the node or its position whose previous node you are searching for:
private MyNode findNode(int pos) {
//node will have pos=pos-1
pos-- = 1;
MyNode prevNode = null;
int count = 0;
MyNode p = first.next; // first = head node, find it however you want.
//this is for circular linked list, you can use first!=last for singly linked list
while (p != first) {
if (count == pos) {
prevNode = p;
break;
}
p = p.next;
count++;
}
return prevNode;
}
We can traverse through the LinkedList using slow and fast pointers.
Let's say
fast pointer fast = fast.next.next
slow pointer slow = slow.next
Slow pointer will be always a previous of the fast pointer, and so we can able to find it.
It can possible to deleteNode if only given node not root or head. How ?
It can achieve by reversing value in node
4-> 2 -> 1 -> 9 given 2 as node to remove. as above other can't access previous node which is correct because singly linked list we don't store predecessor. What can do is swap value of next of give node to given node and change link to next of next of give node
nextNode = node.next // assigning given node next to new pointer
node.val = nextNode.val // replacing value of given node to nextNode value
node.next = nextNode.next // changing link of given node to next to next node.
I tried this approach and its working fine.
assuming you are using forward singly linked list your code should look like
while(node)
{
previous = node
node = node.next
// Do what ever you want to do with the nodes
}