Searching a red black tree through text file - java

I am working on a school project and it's dictionary application using red black tree.. so the program reads a text file and every line has only one word.
when i do my search it gives me that the word is not available if i entered it with different letters size.. for example if the file has the word "Lion" and i searched "lion" in my program it says that the word is not available in dictionary.. here is my search method. And help me please to fix that.
public static int search(Node root,String data)
{
while(!root.isNullLeaf)
{ String temporary=root.data;
if(temporary.equals(data))
{
System.out.print("yaaay "+ root.data +" is found\n");
return 0;
}
if(temporary.compareTo(data)>0)
root=root.left;
if(temporary.compareTo(data)<0)
root=root.right;
}
System.out.println("ouch "+ data+ " not found\n");
return 1;
}

You should use the XXXIgnoreCase functions fore these type of requirements
temporary.equals(data) becomes temporary.equalsIgnoreCase(data) and temporary.compareTo(data) becomes temporary.compareToIgnoreCase(data)
I also corrected parts of the code to simplify your logic
public static int search(Node root,String data) {
while(!root.isNullLeaf) {
String temporary=root.data;
if(temporary.equalsIgnoreCase(data)) {
System.out.print("yaaay "+ root.data +" is found\n");
return 0;
}
int compareResult = temporary.compareToIgnoreCase(data);
if(compareResult > 0)
root = root.left;
else
root = root.right;
}
System.out.println("ouch "+ data+ " not found\n");
return 1;
}

Related

Scanner.hasNext() Causing Input to be Needed Twice

I am working on some homework and have encountered a problem. The program creates a Tree, outputs pre/in/postorder traversals, then saves them to multiple files. The problem I'm having is getting the input. When you type in the input, after you're done typing in what should be the values of different Nodes, you may either type "done" or "exit". "Done" continues the program with the given input, while "exit" just closes the program. The weird thing is, you don't need to type the values of the Nodes twice to create those Nodes later on in the code, but you do have to type "done" or "exit" twice to get the program to listen to you. The code in question is here:
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
fileWriter.write(response + " ");
response = scanner.next();
}
I have found that removing scanner.hasNext() gets it to function properly, but then it takes away sensing the EOF which is necessary for this assignment.
Here are the full three classes used in the program:
P0:
/**
* Sources for this class:
* https://www.w3schools.com/java/java_regex.asp
* https://stackoverflow.com/questions/14353947/how-to-represent-a-single-space-character-in-a-square-bracket-group
* https://upload.wikimedia.org/wikipedia/commons/1/1b/ASCII-Table-wide.svg
*
* Sources for shell script and makefile:
* https://www.cyberciti.biz/faq/run-execute-sh-shell-script/
* https://www.dummies.com/article/technology/computers/operating-systems/linux/linux-how-to-run-make-150284/
* https://www.cs.swarthmore.edu/~newhall/unixhelp/javamakefiles.html
*/
package mikefitzgibbon.p0;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class P0{
public static void main(String args[]) {
File file = new File("file");
String input = "";
//there can only be one or 0 arguments in the command line operation
if(args.length > 1) {
System.out.println("Please only enter the name of 1 file.");
System.exit(1);
}
//if a filename is specified, try getting the input from it
else if(args.length == 1){
file = new File(args[0]);
}
//else read from System.in
else {
Scanner scanner = new Scanner(System.in);
String response;
file = new File("input");
try (FileWriter fileWriter = new FileWriter(file)) {
System.out.println("Please enter strings to put into the tree.");
System.out.println("Type \"done\" to end taking in input, and type \"exit\" to prematurely quit.");
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(scanner.hasNext() && !response.equals("exit") && !response.equals("done")) {
fileWriter.write(response + " ");
response = scanner.next();
}
//exits the program with OK return value
if(response.equals("exit")) {
System.out.println("Prematurely ending program now.");
System.exit(0);
}
}
catch(IOException e){
System.out.println("Had trouble writing to file from System.in.");
}
}
//scans file for strings until there are no more data or eof is reached
try(Scanner scanner = new Scanner(file)){
while(scanner.hasNextLine()){
input += scanner.nextLine() + " ";
}
scanner.close();
}
//exit the program is file name is invalid
catch(FileNotFoundException e){
System.out.println("The file name you entered does not exist.");
System.exit(2);
}
//checks input for characters outside of the appropriate ASCII range
for(char c : input.toCharArray()){
if(!Character.isLetterOrDigit(c) &! Character.isWhitespace(c)) {
System.out.println("Your file or console input was not readable."
+ "\nPlease only use alhpanumeric characters.");
System.exit(3);
}
}
//this is only used as a reference for the filename
if(file.getName().equals("input"))
file = new File("output");
//creates the tree from the input and then converts it to the output
Tree tree = new Tree(input);
//displays the input
System.out.println("Here is your input for the program.");
System.out.println(input);
System.out.println();
//writes to the files
System.out.println("Outputting data to files " +
file.getName() + ".preorder, " +
file.getName() + ".inorder, and " +
file.getName() + ".postorder.");
System.out.println();
System.out.println("Output for " + file +".preorder: ");
tree.printPreorder(file.getName());
System.out.println();
System.out.println("Output for " + file +".inorder: ");
tree.printInorder(file.getName());
System.out.println();
System.out.println("Output for " + file +".postorder: ");
tree.printPostorder(file.getName());
System.out.println();
System.out.println("Ending program now.");
}
}
Tree:
/**
* Sources for this class:
* https://www.w3schools.com/java/java_files_create.asp
* https://www.softwaretestinghelp.com/binary-search-tree-in-java/
* https://www.youtube.com/watch?v=WLvU5EQVZqY&ab_channel=TECHDOSE
*/
package mikefitzgibbon.p0;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Tree {
//nodes that make up this part of the tree
Node root;
//constructor calls the buildTree() function
public Tree(String input){
buildTree(input);
}
//takes a list of strings and a root node and creates the tree structure recursively using the addNode helper function
private void buildTree(String input) {
Scanner scanner = new Scanner(input);
//recursively builds tree with each word
while(scanner.hasNext()){
root = addNode(root,scanner.next());
}
}
private Node addNode(Node root, String value){
//checks root for null and sets it if it is
if(root == null){
root = new Node(value);
return root;
}
//compares the first letter of the input to the root's value and recursively traverses tere
else if(root.getValue().charAt(0) > value.charAt(0))
root.setLeftNode(addNode(root.getLeftNode(),value));
else if(root.getValue().charAt(0) == value.charAt(0))
root.setMiddleNode(addNode(root.getMiddleNode(),value));
else if(root.getValue().charAt(0) < value.charAt(0))
root.setRightNode(addNode(root.getRightNode(),value));
//return root if all else fails
return root;
}
//prints the tree printPreorder recursively
public void printPreorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".preorder")) {
printPreorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the preorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the preorder file.");
}
}
//helper function for printPreorder()
private void printPreorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
try{
String indent = "";
for(int a = 0 ; a < depth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.println(indent + root.getValue().charAt(0) + ":" + root.getValue());
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .preorder file.");
System.exit(4);
}
depth++;
printPreorder(fileWriter, root.getLeftNode(), depth);
printPreorder(fileWriter, root.getMiddleNode(), depth);
printPreorder(fileWriter, root.getRightNode(), depth);
}
//prints the tree printInorder recursively
public void printInorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".inorder")) {
printInorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the inorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the inorder file.");
}
}
//helper function for printInorder()
private void printInorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
int previousDepth = depth;
depth++;
printInorder(fileWriter, root.getLeftNode(), depth);
try{
String indent = "";
for(int a = 0 ; a < previousDepth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .preorder file.");
System.exit(4);
}
printInorder(fileWriter, root.getMiddleNode(), depth);
printInorder(fileWriter, root.getRightNode(), depth);
depth++;
}
//prints the tree printPostorder recursively
public void printPostorder(String filename){
try(FileWriter myWriter = new FileWriter(filename + ".postorder")) {
printPostorder(myWriter, root, 0);
myWriter.close();
System.out.println();
System.out.println("Successfully wrote to the postorder file.");
}
catch (IOException e) {
System.out.println("An error occurred while writing to the postorder file.");
}
}
//helper function for printPostorder()
private void printPostorder(FileWriter fileWriter, Node root,int depth) {
//base case
if(root == null)
return;
//write to file and recursive cases
int previousDepth = depth;
depth++;
printPostorder(fileWriter, root.getLeftNode(), depth);
printPostorder(fileWriter, root.getMiddleNode(), depth);
printPostorder(fileWriter, root.getRightNode(), depth);
try{
String indent = "";
for(int a = 0 ; a < previousDepth ; a++){
indent += " ";
}
fileWriter.write(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
System.out.print(indent + root.getValue().charAt(0) + ":" + root.getValue() + "\n");
}
catch(IOException e){
System.out.println("Something went wrong while writing to the .postorder file.");
System.exit(4);
}
}
//getter and setter
public void setRoot(Node node) {
root = node;
}
public Node getRoot() {
return root;
}
}
Node:
/**
* Sources for this class:
* https://www.softwaretestinghelp.com/binary-search-tree-in-java/
*/
package mikefitzgibbon.p0;
public class Node {
//this is how the tree branches out, 3 children per node
Node left, middle, right;
String value = "";
public Node(String val) {
value=val;
}
//getters and setters
public void setRightNode(Node node) {
right=node;
}
public void setLeftNode(Node node) {
left=node;
}
public void setMiddleNode(Node node) {
middle=node;
}
public Node getRightNode() {
return right;
}
public Node getLeftNode() {
return left;
}
public Node getMiddleNode() {
return middle;
}
public String getValue() {
return value;
}
}
scanner.hasNext() will block (freeze the thread) until user input happens. You might think "No, it would return false, as currently there is no token available - there is no 'next'", but that's not how it works. There indeed may not currently be a next. But who knows what happens from here on out? Perhaps the user types CTRL+C, closing the pipe, thus, hasNext() will now return false, as there will never be a next token. Or, the user types something, and it will then return true, as now clearly there is a next token to be had. That's why it blocks: It cannot give a certain answer until you do something.
This may make no sense - keep in mind that 'standard input' is not the keyboard. It's... whatever stream is hooked up to standard input. By default that is a keyboard, but run your app with java -jar whatever.jar <somefile.txt and now it's that file. Which has a limited size. hasNext() would start returning false once you get to the 'end of the file'. You cannot normally ever get to the 'end of the keyboard', but the abstraction isn't designed solely for keyboards.
In other words, your code:
response = scanner.next();
while(scanner.hasNext() && ....
Will:
Read a token from standard input.
Will... read a token from standard input AGAIN (because hasNext() does that. If it works out, it returns true. If it turns out there is no token now nor will there ever be, it returns false).
This explain why you have to enter input twice. The solution is to remove the hasNext call there. Move it INTO the while loop. Instead of response = scanner.next() inside the loop, do something like:
if (!scanner.hasNext()) return; // or break, or System.exit(0), or whatever you want.
response = scanner.next();
}
I found that putting the scanner.hasNext() at the end of the expression fixed the problem, but I'm not entirely sure how. Here is the updated code:
//gets input from console until "exit" or "done" is typed
response = scanner.next();
while(!response.equals("exit") && !response.equals("done") && scanner.hasNext()) {
fileWriter.write(response + " ");
response = scanner.next();
}

nearest neighbor algorithm copy element (city) to output array java

So I have a program written so far that reads in a csv file of cities and distances in the following format:
Alaska Mileage Chart,Anchorage,Anderson,Cantwell,
Anchorage,0,284,210,
Anderson,284,0,74,
Cantwell,210,74,0,
So the algorithm works and outputs the cities in the order they should be visited following the shortest path using the nearest neighbor algorithm always starting with Anchorage as the city of origin or starting city.
Using this data, the example output for the algorithm is: 1,3,2. I have ran this with a 27 element chart and had good results as well. I am using this small one for writing and debugging purposes.
Ideally the output I am looking for is the Name of the City and a cumulative milage.
Right now I am having working on trying to get the cities into an array that I can print out. Help with both parts would be appreciated or help keeping in mind that is the end goal is appreciated as well.
My thought was that ultimately I may want to create an array of {string, int}
so my output would look something like this..
Anchorage 0
Cantwell 210
Anderson 284
I am able to set the first element of the array to 1, but can not get the 2nd and 3rd element of the new output array to correct
This is the code I am having a problem with:
public class TSPNearestNeighbor {
private int numberOfNodes;
private Stack<Integer> stack;
public TSPNearestNeighbor()
{
stack = new Stack<>();
}
public void tsp(int adjacencyMatrix[][])
{
numberOfNodes = adjacencyMatrix[1].length;
// System.out.print(numberOfNodes);
// System.out.print(Arrays.deepToString(adjacencyMatrix));
int[] visited = new int[numberOfNodes];
// System.out.print(Arrays.toString(visited));
visited[1] = 1;
// System.out.print(Arrays.toString(visited));
stack.push(1);
int element, dst = 0, i;
int min = Integer.MAX_VALUE;
boolean minFlag = false;
System.out.print(1 + "\n");
//System.arraycopy(arr_cities, 0, arr_final, 0, 1); // Copies Anchorage to Pos 1 always
//System.out.print(Arrays.deepToString(arr_final)+ "\n");
while (!stack.isEmpty())
{
element = stack.peek();
i = 1;
min = Integer.MAX_VALUE;
while (i <= numberOfNodes-1)
{
if (adjacencyMatrix[element][i] > 1 && visited[i] == 0)
{
if (min > adjacencyMatrix[element][i])
{
min = adjacencyMatrix[element][i];
dst = i;
minFlag = true;
}
}
i++;
}
if (minFlag)
{
visited[dst] = 1;
stack.push(dst);
System.out.print(dst + "\n");
minFlag = false;
continue;
}
stack.pop();
}
}
Given the existing structure you are using, you can output the cities in the path using:
public void printCities(Stack<Integer> path, int[][] distances, List<String> names) {
int cumulativeDistance = 0;
int previous = -1;
for (int city: path) {
if (previous != -1)
cumulativeDistance += distances[previous][city];
System.out.println(names.get(city) + " " + cumulativeDistance);
previous = city;
}
}
I'd like to answer your question slightly indirectly. You are making life hard for yourself by using arrays of objects. They make the code difficult to read and are hard to access. Things would become easier if you create a City class with appropriate methods to help you with the output.
For example:
class City {
private final String name;
private final Map<City,Integer> connections = new HashMap<>();
public static addConnection(City from, City to, int distance) {
from.connections.put(to, distance);
to.connections.put(from, distance);
}
public int getDistanceTo(City other) {
if (connections.containsKey(other))
return connections.get(other);
else
throw new IllegalArgumentException("Non connection error");
}
}
I've left out constructor, getters, setters for clarity.
Now outputting your path becomes quite a bit simpler:
public void outputPath(List<City> cities) {
int cumulativeDistance = 0;
City previous = null;
for (City current: cities) {
if (previous != null)
cumulativeDistance += previous.getDistanceTo(current);
System.out.println(current.getName + " " + cumulativeDistance);
previous = current;
}
}

Working with Java Trie, fails to identify word endings. Fails somewhere in recursion

I am trying to create my own version of a Java Trie in order to have one, and to gain the knowledge it requires to make one, but this project has me perplexed. I have a very basic broken Trie here.
I am adding 3 words to the Trie (by using the first character of the word as the key, and the value being additional TrieNodes). If you notice, I have print statements inside the TrieNode class to check the values of isWord as the program runs. I want the last character in the word to have the isWord variable set to True. Thus identifying the end of a word (which I will later use to get the whole word).
When I first put the three words in, the output prints every letter of every word as they go into the Trie and correctly identifies which characters are word endings.
However, if IMMEDIATELY after entering words, I traverse the Trie and re-print all characters in the Trie and their isWord status, the 'e' in "Hello" is now suddenly identified as a word ending?
I have poured over this for hours and I just don't see why this is happening. Below is the working code:
package testcode;
import java.util.*;
public class TestCode {
public static Trie t;
public static void main (String[] args){
t = new Trie();
t.addWord("hello");
t.addWord("hi");
t.addWord("soup");
//at this point the output correctly identifies word endings.
t.findWords();
/* but when iterating through the hash map it becomes evident that
* when entering the word 'hi' the 'e' in 'hello' had its isWord variable
* changed to true. I followed the logic and I do not see how or why this
* is happening.
*/
}
}
//This Trie class handles the root trie, and Trie commands.
class Trie{
private TrieNode root;
public Trie(){
root = new TrieNode();
}
public void addWord(String word){
root.addWord(word.toLowerCase());
}
public void findWords(){
root.findWords();
}
}
//Trie Node handles the nodes and words within the trie
class TrieNode{
private TrieNode parent;
private boolean isWord;
private boolean hasChildren;
private char character;
private Map<Character, TrieNode> children = new HashMap<>();
public TrieNode(){
hasChildren = false;
isWord = false;
}
public TrieNode(String word){
this();
addWord(word);
}
public void addWord(String word){
char firstChar = word.charAt(0);
if (children.get(firstChar) == null){
if(word.length() > 1){
hasChildren = true;
children.put(firstChar, new TrieNode(word.substring(1)));
children.get(firstChar).parent = this;
System.out.print(firstChar + "--");
System.out.println(isWord);
}
else{
children.put(firstChar, new TrieNode());
if(character == 'e'){
System.out.println("shits about to go down");
}
isWord = true;
System.out.print(firstChar + "--");
System.out.println(isWord);
}
children.get(firstChar).character = firstChar;
}
else {
children.get(firstChar).addWord(word.substring(1));
}
}
public void findWords(){
for(Character key : children.keySet()){
children.get(key).findWords();
System.out.println(children.get(key).character + " -- " + isWord);
}
}
}
This code generates the following output:
o--true
l--false
l--false
e--false
h--false
i--true
p--true
u--false
o--false
s--false
p -- true
u -- false
o -- false
s -- false
o -- true
l -- false
l -- false
e -- true //notice the e here is now suddenly a word ending with isWord = true
i -- true
h -- false
There were a range of possible issues.. Parent/Child confusion, handling Leaf cases at the Parent Node, both in building & printout etc.
I note in your old 'findWords' code, you were printing child character but parent 'isWord' flag. Building the trie had undesirable divergence between "child node exist" and "create child node paths" -- such that 'isWord' could only be flagged on new paths, not existing paths. Building the trie also appeared to set 'isWord' on the parent rather than the leaf node.
In general, code that's a spaghetti of nested IF cases is highly likely to be unreliable. Code should be common where possible -- keep it in the main flow of the method, unless it really does belong inside the IF.
Here's clean & correct code:
class TrieNode{
private TrieNode parent;
private boolean isWord;
private boolean hasChildren;
private char character;
private Map<Character, TrieNode> children = new HashMap<>();
public TrieNode(){
this.hasChildren = false;
this.isWord = false;
}
public TrieNode (char ch) {
this.character = ch;
this.hasChildren = false;
this.isWord = false;
}
public void addWord (String word){
if (word.length() == 0) {
this.isWord = true;
System.out.println( character + " -- " + isWord);
return;
}
// represent the Child Node;
// --
char firstChar = word.charAt(0);
TrieNode child = children.get( firstChar);
if (child == null){
child = new TrieNode( firstChar);
children.put( firstChar, child);
child.parent = this;
hasChildren = true;
}
// add Remaining Word;
// -- call for 1-length words, as 0-length at Child sets 'IsWord'!
child.addWord( word.substring(1));
// print building here.
System.out.println( character + " -- " + isWord);
}
public void findWords(){
for(Character key : children.keySet()){
children.get(key).findWords();
}
System.out.println( character + " -- " + isWord);
}
}

Binary Search output issue?

This is a first for using a binary search for me, so I've run into a small issue (hopefully!) first the program, it allows the user to type in a random number, and if that number matches any book it outputs the title.
class b {
String book1, book2;
b () {
book1 = "Wicked Awesome Title";
book2 = "How to Read a Book";
public static Book getBook(Book [] A, int left, int right, String bookTitle) {
int middle;
Book found = null;
/**Your average Joe binary search...*/
while (found == null && left <= right) {
//If middle item == 0, returns true
middle = (left + right)/2;
int compare = A[middle].sameTitle(bookTitle);
if (compare == 0) {
found = A[middle];
} else {
if (compare >0) {
right = middle -1;
} else {
left = middle + 1;
}
}
}
return found;
}
Now this is the problem, after pressing the "find" book button,
private void findActionPerformed(java.awt.event.ActionEvent evt) {
String book1 = "Wicked Awesome Title";
String book2 = "How to Read a Book";;
Book b = getBook(book1, book2); //this entire line is underlined,
if (b != null){
itsATextField.setText("You've found the book " + b);
}
so what am I missing to make this work? Any ideas?
Your getBook function is declared as:
public static Book getBook(Book [] A, int left, int right, String bookTitle) {
When you try to call it only with two String arguments:
Book b = getBook(book1, book2);
If you want to call a function, you must call it with the expected arguments.
Also, not sure if related or not but you'r missing } at the end of the constructor.
BTW, adding the error you get will help us help you.

Java Need help implementing an algorithm

This algorithm is so advanced for my basic programming skills that I just don't see how I could implement it. I'm posting this in a new question because I can't keep bothering the guy who gave me the algorithm alone about this in the comment section in the previous question.
MaxSet(node) = 1 if "node" is a leaf
MaxSet(node) = Max(1 + Sum{ i=0..3: MaxSet(node.Grandchildren[i]) },
Sum{ i=0..1: MaxSet(node.Children[i]) })
Thanks too mehrdad for the algorithm.
The problem here for me is to implement the part of the two sum lines, how can I do that? And I need to mark every node that this algorithm chooses. It's just a "marked" variable in the node class set to true. I don't understand were it makes a decision too choose a node?
EDIT to include my code so far:
public int maxSet(Posisjon<E> bt){
if (isExternal(bt)){
return 1;
}
return Math.max(1 + helper1(bt), helper2(bt));
}
private int helper1(Posisjon<E> node){
int tmp = 0;
if (hasLeft(node)){
if(hasLeft((Position<E>)node.leftChild())){
tmp += maxSet(node.leftChild().leftChild());
}
if(hasRight((Position<E>)node.leftChild())){
tmp += maxSet(node.leftChild().rightChild());
}
}
if(hasRight(node)){
if(hasLeft((Position<E>)node.rightChild())){
tmp += maxSet(node.leftChild().leftChild());
}
if(hasRight((Position<E>)node.rightChild())){
tmp += maxSet(node.leftChild().rightChild());
}
}
return tmp;
}
private int helper2(Posisjon<E> node){
int tmp = 0;
if(hasLeft(node)){
tmp +=maxSet(node.leftChild());
}
if(hasRight(node)){
tmp +=maxSet(node.rightChild());
}
return tmp;
}
This seems to be working, what is left now. Is to actually mark the nodes as chosen? Were would I do that?
Updated with code:
public ArrayList<Posisjon<E>> getSelectionSet(Posisjon<E> bt, ArrayList<Posisjon<E>> s){
if(bt.marked){
s.add(bt);
}
if(hasLeft(bt)){
if(hasLeft(bt.leftChild())){
getSelectionSet(bt.leftChild().leftChild(),s);
}
if(hasRight(bt.leftChild())){
getSelectionSet(bt.leftChild().rightChild(),s);
}
}
if(hasRight(bt)){
if(hasLeft(bt.rightChild())){
getSelectionSet(bt.rightChild().leftChild(),s);
}
if(hasRight(bt.rightChild())){
getSelectionSet(bt.rightChild().rightChild(),s);
}
}
return s;
}
public int maxSet(Posisjon<E> bt){
if (bt.visited){
return bt.computedMax;
}
bt.visited = true;
int maxIfCurrentNodeIsSelected = 1 + helper1(bt);
int maxIfCurrentNodeIsNotSelected = helper2(bt);
if (maxIfCurrentNodeIsSelected > maxIfCurrentNodeIsNotSelected){
bt.marked = true;
bt.computedMax = maxIfCurrentNodeIsSelected;
}else{
bt.marked = false;
bt.computedMax = maxIfCurrentNodeIsNotSelected;
}
return maxSet(bt);
}
After submission, I will post the entire code for this!
You currently have does not memoize the return value of the function each time. Every time you call maxSet, you should check if you have already computed the result or not. If you have, just return it. If you haven't compute it and store it somewhere. Otherwise, your algorithm will be inefficient. (This approach is called "Dynamic Programming." Learn about it.)
// pseudocode:
public int maxSet(Posisjon<E> bt){
if (visited[bt])
return computedMax[bt];
visited[bt] = true;
// You don't need to manually check for being a leaf
// For leaves 'maxIfCurrentNodeIsSelected' is always larger.
int maxIfCurrentNodeIsSelected = 1 + helper1(bt);
int maxIfCurrentNodeIsNotSelected = helper2(bt);
if (maxIfCurrentNodeIsSelected > maxIfCurrentNodeIsNotSelected) {
shouldSelect[bt] = true;
computedMax[bt] = maxIfCurrentNodeIsSelected;
} else {
shouldSelect[bt] = false;
computedMax[bt] = maxIfCurrentNodeIsNotSelected;
}
}
public Set getSelectionSet(Posisjon<E> bt, Set s) {
if (shouldSelect[bt]) {
s.Add(bt);
// You should check for nulls, of course
getSelectionSet(bt.leftChild.leftChild, s);
getSelectionSet(bt.leftChild.rightChild, s);
getSelectionSet(bt.rightChild.leftChild, s);
getSelectionSet(bt.rightChild.rightChild, s);
} else {
getSelectionSet(bt.leftChild, s);
getSelectionSet(bt.rightChild, s);
}
return s;
}
call getSelectionSet with the root node and an empty Set as arguments after you called maxSet.

Categories

Resources