This question already has answers here:
Java Printing a Binary Tree using Level-Order in a Specific Format
(23 answers)
Closed 8 years ago.
PS: This is NOT HOMEWORK. And I didn't understand the other question answer's, otherwise I wouldnt be opening a new one...
I'm trying to print this tree:
3
/ \
7 2
/ \ \
0 9 11
/ \ / \
1 2 6 4
As a level order output:
3
7 2
0 9 11
1 2 6 4
The problem is my code can only print trees like this: 3 7 2 0 9 11 1 2 64, which is the same as the last numbers but without a paragraph or '\n'. I can't seem to find an easy way to do this (preferencially without using foreach). Someone told me I should create a variable: 'level' on the tree that classifies in which level the node is, but how can I even classify the levels?
Can you help me?
public void largura() { //just an auxiliar method to call 'larguras'
larguras(root);
System.out.println();
}
private void larguras(Node t) {
LinkedList<Node> f = new LinkedList<Node>();
Node r;
f.add(t);
while (!f.isEmpty()) {
r=f.remove();
if (r!=root) System.out.print(" ");
System.out.print(r.value);
if (r.left != null) f.add(r.left);
if (r.right != null) f.add(r.right);
}
}
Hmmm... Would something like this work?
//Prints the tree in level order
public void printTree(){
printTree(root);
}
public void printTree(TreeNode tmpRoot){
//If the first node isn't null....continue on
if(tmpRoot != null){
Queue<TreeNode> currentLevel = new LinkedList<TreeNode>(); //Queue that holds the nodes on the current level
Queue<TreeNode> nextLevel = new LinkedList<TreeNode>(); //Queue the stores the nodes for the next level
int treeHeight = height(tmpRoot); //Stores the height of the current tree
int levelTotal = 0; //keeps track of the total levels printed so we don't pass the height and print a billion "null"s
//put the root on the currnt level's queue
currentLevel.add(tmpRoot);
//while there is still another level to print and we haven't gone past the tree's height
while(!currentLevel.isEmpty()&& (levelTotal< treeHeight)){
//Print the next node on the level, add its childen to the next level's queue, and dequeue the node...do this until the current level has been printed
while(!currentLevel.isEmpty()){
//Print the current value
System.out.print(currentLevel.peek().getValue()+" ");
//If there is a left pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.peek().getLeft();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
//If there is a right pointer, put the node on the nextLevel's stack. If there is no ponter, add a node with a null value to the next level's stack
tmpRoot = currentLevel.remove().getRight();
if(tmpRoot != null)
nextLevel.add(tmpRoot);
else
nextLevel.add(new TreeNode(null));
}//end while(!currentLevel.isEmpty())
//populate the currentLevel queue with items from the next level
while(!nextLevel.isEmpty()){
currentLevel.add(nextLevel.remove());
}
//Print a blank line to show height
System.out.println("");
//flag that we are working on the next level
levelTotal++;
}//end while(!currentLevel.isEmpty())
}//end if(tmpRoot != null)
}//end method printTree
public int height(){
return height(getRoot());
}
public int height(TreeNode tmpRoot){
if (tmpRoot == null)
return 0;
int leftHeight = height(tmpRoot.getLeft());
int rightHeight = height(tmpRoot.getRight());
if(leftHeight >= rightHeight)
return leftHeight + 1;
else
return rightHeight + 1;
Or perhaps something like this:
public void BFSPrint()
{
Queue<Node> q = new LinkedList<Node>();
q.offer(root);
BFSPrint(q);
}
private void BFSPrint(Queue<Node> q)
{
if(q.isEmpty())
return;
int qLen = q.size(),i=0;
/*limiting it to q size when it is passed,
this will make it print in next lines. if we use iterator instead,
we will again have same output as question, because iterator
will end only q empties*/
while(i<qLen)
{
Node current = q.remove();
System.out.print(current.data+" ");
if(current.left!=null)
q.offer(current.left);
if(current.right!=null)
q.offer(current.right);
i++;
}
System.out.println();
BFSPrint(q);
}
Essentially you are doing something like this:
http://leetcode.com/2010/09/printing-binary-tree-in-level-order.html
The code above will not work for a tree of more than 3 levels that's for you to figure out.
# commenter / -1'er I gave an example so they can play with it. It would appear that this is either homework or a sample exercise and I find playing with the code itself is more helpful to learning. Thats why I gave multiple implementations.
Related
I want to implement dfs for nodes that are of type long in Java.
My algorithm calculates correctly the number of nodes, and the number
of edges, but not the sequence of nodes. Could you please help me
modify my algorithm so I calculate the order in which the nodes are
visited, correctly?
This is my code:
private int getNumberOfNodes(long firstNode) {
List<Long> marked = new ArrayList<>(); //------------------------------------------->
Stack<Long> stack = new Stack<Long>(); //step 1 Create/declare stack
stack.push(firstNode); //Step 2 Put/push inside the first node
while (!stack.isEmpty()) { //Repeat till stack is empty:
Long node = stack.pop(); //Step 3 Extract the top node in the stack
marked.add(node); //------------------------------------------->
long[] neighbors = xgraph.getNeighborsOf(node); //Get neighbors
if (neighbors.length % 2 == 0) {
} else {
numOfNodesWithOddDegree++;
}
int mnt = 0;
for (long currentNode : neighbors) {
if (!marked.contains(currentNode) && !stack.contains(currentNode) ) { //&& !stack.contains(currentNode)
stack.push(currentNode);
} else {
}
if (!marked.contains(currentNode)) {
numOfEdges++;
}
}
}
return marked.size(); //(int) Arrays.stream(neighbors).count();
}
I guess you exam the marked list for the sequence.
As your graph is undirected, the sequence of traversals could be varied based on which neighbor you pushed into the stack first. which means the logic of your function:
xgraph.getNeighborsOf(node)
could impact your sequence. see Vertex orderings from this wiki https://en.wikipedia.org/wiki/Depth-first_search
so my conclusion is: you may have a different traversal sequence, it does not mean your DFS is wrong, as long as it is Deep first search, it is ok to be a little bit different from the given answer.
Hello I'm a low level comp sci student that's really struggling/unfamiliar with file i/o.
I'm attempting to read in a text file using buffered reader. I understand how to use a while loop to continue scanning until the end of the file is reached but how can I instruct my reader to read just one line and do something until the end of that one line is reached, then read the next line and do something until that line ends, etc?
basically my input text file is going to repeat every three lines. The text file represents nodes in a weighted directed graph.
The input text file would supposedly look like the following:
each node is represented by two lines of text. For example the on the very top line, the first 'S' is the name of the node, the second 'S' indicates that it's a start node, the third 'n' indicates that it's a regular node, not a goal node, which would be indicated by a 'g'.
On the second line are the two nodes connected to 'S' the first being 'B' with a weighted distance of 1, and the second being 'E' with a weighted distance of 2.
The third line is supposed to be blank, and the pattern is repeated.
S S n
B 1 E 2
B N n
C 2 F 3
C N n
D 2 GA 4
D N n
GA 1
E N n
B 1 F 3 H 6
F N n
I 3 GA 3 C 1
GA N g
H N n
I 2 GB 2 F 1
I N n
GA 2 GB 2
GB N g
My code is as follows:
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == openButton)
{
returnVal = fileChooser.showOpenDialog(null);
if(returnVal == JFileChooser.APPROVE_OPTION)
{
selected_file = fileChooser.getSelectedFile();
String file_name = fileChooser.getSelectedFile().getName();
file_name = file_name.substring(0, file_name.indexOf('.'));
try
{
BufferedWriter buff_writer = null;
File newFile = new File("."+file_name+"_sorted.txt");
boolean verify_creation = newFile.createNewFile();
//if (verify_creation)
// System.out.println("file created successfully");
//else
// System.out.println("file already present in specified location");
file_reader1 = new BufferedReader(new FileReader(selected_file));
file_reader2 = new BufferedReader(new FileReader(selected_file));
FileWriter file_writer = new FileWriter(newFile.getAbsoluteFile());
buff_writer = new BufferedWriter(file_writer);
//find the number of nodes in the file
while( (currentLine = file_reader1.readLine()) != null)
{
k++;
//System.out.println("value of k: " + k);
}
nodeArray = new Node[k];
while( (currentLine = file_reader2.readLine()) != null)
{
//System.out.print(currentLine);
String[] var = currentLine.split(" ");
nodeArray[x] = new Node(var[0]);
if (var[1].equals('S') || var[1].equals('s'))
nodeArray[x].setType(NodeType.START);
else if (var[2].equals('g') || var[2].equals('G'))
nodeArray[x].setType(NodeType.GOAL);
else
nodeArray[x].setType(NodeType.NORMAL);
x++;
}
buff_writer.close();
file_writer.close();
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
My node class is as follows:
import java.util.*;
enum NodeType
{
START, GOAL, NORMAL;
}
public class Node
{
private String name;
private NodeType typeOfNode;
private final Map<Node, Integer> neighbors = new HashMap<>();
public Node(String name)
{
this.name = name;
}
public void setType(NodeType type)
{
typeOfNode = type;
}
public void addAdjacentNode(Node node, int distance)
{
neighbors.put(node, distance);
}
public String toString()
{
String output = "";
output += "node name: " + name + ",\n";
return output;
}
}
My other major problem is how to handle the second line in the repeating three line sequence. The second line gives all the adjacent nodes and their weighted distances from the node described on the first line. The problem is, I don't know how many adjacent nodes will exist for any given node. Technically there could be none, or maybe a large number.
A kind programmer here suggested that I use a hash map to record adjacent nodes but I'm not sure how to structure a line of code to account for an indeterminate number of such adjacencies
Note: this question is in reference to this earlier question I asked: how to create an adjacency matrix, using an input text file, to represent a directed weighted graph [java]?
if anyone could point me in the right direction I would be eternally grateful
As far as the input problem goes, your while loop is treating every line it reads identically. You will have to add a variable to keep track of which line in the 3-line sequence you're dealing with.
As for the adjacent nodes use an ArrayList, which is a dynamically sized array.
You need an ArrayList for each node, which stores information about that node's adjacent nodes.
So you will need an array containing (k divided by 3) ArrayLists.
Im writing the method to print a binary search tree in order. I figured out a way to do this but it requires either the deletion or nullify nodes as they are printed. Below is my code:
public String printKeysInOrder() {
String output = "";
if (isEmpty()) return "()";
else{
int i = 0;
while(i!=size()){
Node x = root;
int loopBreak = 0;
while(loopBreak!=1){
if(x.left != null) x = x.left;
else if (x.right != null){
output = output + " " + x.val;
x.key = null;
x = x.right;
i++;
}
else{
output = output + " " + x.val;
x.key = null;
loopBreak = 1;
}
}
i++;
}
}
return output;
}
for the tree:
_7_
/ \
_3_ 8
/ \
1 6
\ /
2 4
\
5
it should print "1 2 3 4 5 6 7 8"
the code works in a way that it favors moving left through the tree until it can no longer go left, it then stores that node's value in the string output, makes the nodes key equal to null (as so future iterations of the loop do not go down that tree) and moves right if possible or iterates back around the loop.
Although i'm having trouble making it so the node equals null, as when the code is executed (via junit test) the code doesnt recognize that null key and goes through that subtree anyway? Can anyone help me out or tell me how to make it so the x.left and x.right pointers on future iterations recognize the node as null?
You don't need to nullify or delete nodes you need a traversal algorithm.
The in-order traversal provided here should work without major modification:
http://www.javabeat.net/binary-search-tree-traversal-java/
Another object-oriented approach to this is a Visitor supplied to an in-order traversable which allows you to supply the action performed at each node whether it be printing, collecting, mapping, or something else.
I know how to calculate the diameter of tree but I want to print all possible diameters of tree. Taking the below example:-
1
/ \
2 3
/ / \
4 5 6
All Possible diameters in above tree are:-
First: 4 2 1 3 5
Second: 4 2 1 3 6
Any help regarding approach will very helpful.
I assume you mean all possible paths of maximal length from one leaf to another?
Recursion may be your best bet - in pseudocode something like:
path(startNode, endNode) {
if startNode = endNode return;
for each possible next node n {
add n to your path;
path(n, endNode);
}
}
You could call this for each pair of leaves then throwaway any non-maximal length paths, or perhaps choose which leaves to call this on in a bit more of a smart way, which I would leave up to you
How is this done in graphs:
Run BFS from any node n to find most distant node (from that node) n'
Run BFS from node n' to his most distant node n''
The path from n' to n'' is the tree diameter
So, looking at a tree (which can be unrolled into a graph):
A diameter path goes from any leaf on the lowest level in the left sub-tree to any leaf on the lowest level in the right sub-tree.
Now, since you don't don't magically know which 2 nodes are the end nodes of a diameter, and you only have parent-to-child links, the above algorithm wont work, per se. However, you can use the analogy to build one that works on trees instead of graphs.
OK, here is some quick code you can use (it may not be optimal, but it works)
public class BinarySearchTree {
...
public Iterable<T> diameter() {
if (this.root == null) {
return null;
}
Deque<T> diameterLeftPart = new ArrayDeque<T>();
Deque<T> diameterRightPart = new ArrayDeque<T>();
diameter(this.root.left, diameterLeftPart);
diameter(this.root.right, diameterRightPart);
Deque<T> diameter = new ArrayDeque<T>();
for (Iterator<T> it = diameterLeftPart.iterator(); it.hasNext();) {
diameter.offerLast(it.next());
}
diameter.offerLast(this.root.item);
for (Iterator<T> it = diameterRightPart.descendingIterator(); it.hasNext();) {
diameter.offerLast(it.next());
}
return diameter;
}
private void diameter(Node node, Deque<T> diameter) {
if (node == null) {
return;
}
Deque<T> leftPart = new ArrayDeque<T>();
Deque<T> rightPart = new ArrayDeque<T>();
diameter(node.left, leftPart);
diameter(node.right, rightPart);
if (leftPart.size() > rightPart.size()) {
diameter.addAll(leftPart);
} else {
diameter.addAll(rightPart);
}
diameter.offerLast(node.item);
}
...
}
And the runner class:
public class TreeDiameter {
public static void main(String[] args) {
Tree<Integer> tree = new BinarySearchTree<Integer>();
tree.add(5);
tree.add(2);
tree.add(8);
tree.add(1);
tree.add(3);
tree.add(7);
tree.add(9);
tree.add(4);
tree.add(6);
for (Integer diameterNode : tree.diameter()) {
System.out.print(diameterNode + " ");
}
}
}
With the following output:
4 3 2 5 8 7 6
Quick explanation:
We know that the root is the integral part of the diameter path.
So, we want to get the longest path in the left sub-tree and the longest path in the right sub-tree.
Glued together, they create a diameter.
Using recursive calls diameter(node.left, leftPart) and diameter(node.right, rightPart), leftPart and rightPart contain longest paths in left and right sub-trees, respectively.
Simply comparing their sizes gives us the indication which one we will use in constructing the diameter for one level up the tree.
So, to sum up:
Recursion first goes all the way down to the tree and returns the longest path in that sub-tree, passing it upwards to its parent, all the way up to the root.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
So for example if the original list x was 3 5 6 8 9 2, the new linked list h would be 3 6 9
So I thought my method was working and being awesome but when the original list had more than 3 elements, my list odd doesn't seem to be linked to the next node when list odd has more than 3 elements.
I believe the problem is in my for loop when the condition of my odd List isn't empty.
So if u guys can let me know what I need to do i would appreciate it a lot!
Since I'm new here it wont let me just add a print screen of my method so here is the best next thing :
public static Node oddPosition( iNode x){
int count = 1;
iNode oddList = null;
for(Node temp = h; temp != null; temp = temp.next){
if(count % 2 != 0 ){//<-----declares whether the position is odd or not
//if oddList is empty
if(oddList == null){
oddList = new Node(temp.item);
oddList.next = null;
}
//if oddList is not empty
oddList.next = new Node(temp.item);//<----here is where I believe the problem is for some reason my linked list isnt linking together
oddList.next.next = null;
}
count++;
}
System.out.print("Odd list : ");
print(oddList);
return oddList;
}
Output :
Original list : 3 5 6 8 9 2
What is should display : 3 6 9
What I am getting : 3 9
You keep adding new elements to oddList.next. ou never change value of oddList so this way your result has only the first element and the last element. Somewhere you have to assign oddList = oddList.next to be able to add new values to the end of your list. And you probably also want to keep the first node in a separate value, for example startOfList.
So the result could be something like this:
public static Node oddPosition( iNode x){
int count = 1;
iNode oddList = null;
iNode startOfList = null;
for(Node temp = h; temp != null; temp = temp.next){
if(count % 2 != 0 ){//<-----declares whether the position is odd or not
//if oddList is empty
if(oddList == null){
oddList = new Node(temp.item);
startOfList = oddList;
oddList.next = null;
}
//if oddList is not empty
oddList.next = new Node(temp.item);
oddList.next.next = null;
oddList = oddList.next;
}
count++;
}
System.out.print("Odd list : ");
print(startOfList);
return startOfList;
}