I am trying to implement an insert method of the Paricia trie data structure. I handled many cases but currently I am stuck in the case to differ these both cases:
case 1: Inserting the following 3 strings:
abaxyxlmn, abaxyz, aba
I could implement this case with the code below.
case 2: Inserting the following 3 strings:
abafg, abara, a
In the second case I do not know how to differ between the first and the second case since I need a clue to know when should I append the different substring ab to the childern edge to get abfa, abra. Finally, add ab as a child too to the node a. Please see the image below.
Code:
package patriciaTrie;
import java.util.ArrayList;
import java.util.Scanner;
public class Patricia {
private TrieNode nodeRoot;
private TrieNode nodeFirst;
// create a new node
public Patricia() {
nodeRoot = null;
}
// inserts a string into the trie
public void insert(String s) {
if (nodeRoot == null) {
nodeRoot = new TrieNode();
nodeFirst = new TrieNode(s);
nodeFirst.isWord = true;
nodeRoot.next.add(nodeFirst);
} else {
// nodeRoot.isWrod = false;
insert(nodeRoot, s);
}
}
private String checkEdgeString(ArrayList<TrieNode> history, String s) {
StringBuilder sb = new StringBuilder();
for (TrieNode nextNodeEdge : history) {
int len1 = nextNodeEdge.edge.length();
int len2 = s.length();
int len = Math.min(len1, len2);
for (int index = 0; index < len; index++) {
if (s.charAt(index) != nextNodeEdge.edge.charAt(index)) {
break;
} else {
char c = s.charAt(index);
sb.append(c);
}
}
}
return sb.toString();
}
private void insert(TrieNode node, String s) {
ArrayList<TrieNode> history = new ArrayList<TrieNode>();
for (TrieNode nextNodeEdge : node.getNext()) {
history.add(nextNodeEdge);
}
String communsubString = checkEdgeString(history, s);
System.out.println("commun String: " + communsubString);
if (!communsubString.isEmpty()) {
for (TrieNode nextNode : node.getNext()) {
if (nextNode.edge.startsWith(communsubString)) {
String substringSplit1 = nextNode.edge
.substring(communsubString.length());
String substringSplit2 = s.substring(communsubString
.length());
if (substringSplit1.isEmpty() && !substringSplit2.isEmpty()) {
// 1. case: aba, abaxyz
} else if (substringSplit2.isEmpty()
&& !substringSplit1.isEmpty()) {
// 2. case: abaxyz, aba
ArrayList<TrieNode> cacheNextNode = new ArrayList<TrieNode>();
System.out.println("node edge string is longer.");
if (nextNode.getNext() != null && !nextNode.getNext().isEmpty()) {
for (TrieNode subword : nextNode.getNext()) {
subword.edge = substringSplit1.concat(subword.edge); //This line
cacheNextNode.add(subword);
}
nextNode.getNext().clear();
nextNode.edge = communsubString;
nextNode.isWord = true;
TrieNode child = new TrieNode(substringSplit1);
child.isWord = true;
nextNode.next.add(child);
for(TrieNode node1 : cacheNextNode){
child.next.add(node1);
System.out.println("Test one");
}
cacheNextNode.clear();
}else{
nextNode.edge = communsubString;
TrieNode child = new TrieNode(substringSplit1);
child.isWord = true;
nextNode.next.add(child);
System.out.println("TEST");
}
} else if(substringSplit1.isEmpty() && substringSplit2.isEmpty()){
//3. case: aba and aba.
nextNode.isWord = true;
}else {
// 4. Case: abauwt and abaxyz
//if(nextNode.getNext().isEmpty())
}
break;
}
}
} else {
// There is no commun substring.
System.out.println("There is no commun substring");
TrieNode child = new TrieNode(s);
child.isWord = true;
node.next.add(child);
}
}
public static void main(String[] args) {
Patricia p = new Patricia();
Scanner s = new Scanner(System.in);
while (s.hasNext()) {
String op = s.next();
if (op.equals("INSERT")) {
p.insert(s.next());
}
}
}
class TrieNode {
ArrayList<TrieNode> next = new ArrayList<TrieNode>();
String edge;
boolean isWord;
// To create normal node.
TrieNode(String edge) {
this.edge = edge;
}
// To create the root node.
TrieNode() {
this.edge = "";
}
public ArrayList<TrieNode> getNext() {
return next;
}
public String getEdge() {
return edge;
}
}
}
Related
I am trying to read from a file and store the data into a single linked lists.
The data should have information about a user including id of type long, name of type string, and threat level of type int. Moreover, I am wondering how to read from the file and store into the linked list so that I can then do several operations.
my attempt:
class POI
public class POI {
private long id;
private String name;
private int level;
public POI(){
}
public POI(long n, String s, int l){
id = n;
name = s;
level = l;
}
public void setID (long n){
id = n;
}
public void setName (String s){
name = s;
}
public void setLevel (int l){
level = l;
}
public long getID(){
return id;
}
public String getName(){
return name;
}
public int getLevel(){
return level;
}
}
class POIList
public class POIList {
static private class Node {
int data;
Node next;
Node () {
data = 0;
next = null;
}
Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
public static void print(Node head) {
while (head != null) {
System.out.print(head.data + ", ");
head = head.next;
}
System.out.println();
}
public Node insertNode(Node head, Node insertee, int position) {
if (position < 0) {
System.out.println("Invalid position given");
return head;
}
if (head == null) {
return insertee;
}
if (position == 0) {
insertee.next = head;
return insertee;
}
int i = 0;
Node current=head;
while (i < position - 1 && current.next != null) {
current = current.next;
i++;
}
if (i == position - 1) {
insertee.next = current.next;
current.next = insertee;
} else {
System.out.println("Position was not found.");
}
return head;
}
static Node swapNode(Node head,
int position1, int position2) {
if(position1 < 0 || position2 < 0)
System.out.println("InvalidPos");
Node n1 = null;
Node n2 = null;
Node prev1=null;
Node prev2=null;
int maxPosition = Math.max(position1, position2);
if (position1==maxPosition){
position1=position2;
position2=maxPosition;
}
Node temp=head;
for (int i = 0;i <= maxPosition; i++) {
if (temp == null) {
System.out.println("InvalidPos");
return head;
}
if (i==position1-1) prev1=temp;
if(i == position1) n1 = temp;
if (i==position2-1) prev2=temp;
if(i == position2) n2 = temp;
temp = temp.next;
}
temp = n2.next;
if (prev1!=null){
prev1.next=n2;
}else{
head=n2;
}
if (position2-position1==1){
n2.next=n1;
}else{
n2.next=n1.next;
}
if (prev2!=null){
prev2.next=n1;
}else{
head=n1;
}
n1.next=temp;
return head;
} // End of swapNode
public static Node removeNode(Node head, int position) {
if (position < 0 || head == null) {
System.out.println("Invalid position given");
return head;
}
if (position == 0) {
return head.next;
}
int i = 0;
Node current = head;
while (i < position - 1 && current.next != null) {
current = current.next;
i++;
}
if (current.next != null) {
current.next = current.next.next;
} else {
System.out.println("Position was not found.");
}
return head;
}
}
class AnalyzePOI
public class AnalyzePOI {
public static void main (String [] args) throws FileNotFoundException, IOException{
Scanner scan = new Scanner(System.in);
int choice;
System.out.print("Input filename:");
String filename = scan.nextLine();
File file = new File(filename);
Scanner reader = new Scanner(file);
POIList list = new POIList();
System.out.println("What operation would you like to implement? ");
choice = scan.nextInt();
switch (choice) {
case 1 : print(list) ;
break ;
case 2 : search(reader, list) ;
break ;
case 3 : insert(scan, list);
break ;
case 4 : swap(reader, list);
break ;
case 5 : remove1(reader, list);
break;
case 6 : remove2(reader, list);
break;
case 7 : output();
break;
case 8 :
System.out.println ("Program Terminated");
System.exit(0);
break;
}
start(scan,file, reader );
}
public static void start (Scanner scan, File file, Scanner reader){
String content = new String();
int count=1;
File file1 = new File("abc.txt");
LinkedList<String> list = new LinkedList<String>();
try {
Scanner sc = new Scanner(new FileInputStream(file));
while (sc.hasNextLine()){
content = sc.nextLine();
list.add(content);
}
sc.close();
}catch(FileNotFoundException fnf){
fnf.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
System.out.println("\nProgram terminated Safely...");
}
Collections.reverse(list);
Iterator i = (Iterator) list.iterator();
while (((java.util.Iterator<String>) i).hasNext()) {
System.out.print("Node " + (count++) + " : ");
System.out.println();
}
}
public static void print(POIList list) {
list.print(null);
}
public static void search(Scanner scan, POIList list) {
int id;
String name;
System.out.println("Do you want to enter id or name to search for record: ");
String answer = scan.next();
if (answer == "id"){
System.out.println ("Enter the id to find the record: ");
id = scan.nextInt();
}
else if (answer == "name"){
System.out.println("Enter the name to find the record: ");
name = scan.nextLine();
}
else{
System.out.println("Invalid input");
}
}
public static void insert(Scanner scan, POIList list) {
System.out.println("Enter the the location index ");
int index = 0;
long p1;
int level;
String name;
try {
System.out.println("Index: ") ;
index= scan.nextInt() ;
System.out.println("ID: ") ;
p1=scan.nextLong() ;
System.out.println("Name: ");
name = scan.nextLine();
System.out.println("Threat Level ") ;
level=scan.nextInt() ;
}
catch (InputMismatchException e) {
System.out.print("Invalid Input") ;
}
list.insertNode(null, null, index);
}
public static void swap(Scanner scan, POIList list) {
System.out.println("Enter index 1 to swap record: ");
int index1 = scan.nextInt();
System.out.println("Enter index 2 to swap record: ");
int index2 = scan.nextInt();
list.swapNode(null, index1, index2);
}
public static void remove1(Scanner scan, POIList list) {
int index= 0;
try{
System.out.println("Enter ID to remove a record: ") ;
index=scan.nextInt() ;
}
catch (InputMismatchException e) {
System.out.print("Invalid Input") ;
}
list.removeNode(null, index) ;
}
public static void remove2(Scanner scan, POIList list){
int index = 0;
try{
System.out.println("Enter threat level to remove a record: ");
index=scan.nextInt() ;
}
catch (InputMismatchException e){
System.out.println("Invalid Input");
}
list.removeNode(null, index) ;
}
public static void output() {
}
}
Assuming from your question, you would like to know how to read the file that contains "String" "long" and an "int" value. Let's suppose your input file would look like this as given below.
First, we need to know how the data would look like. I'm assuming that the I/P would look something like this
1 OneString 10
2 TwoSTring 20
Now, the order I'm assuming is "long" "String" "int" with a space in between for each line. Use bufferedReader for faster reading.
FileReader fr = new FileReader("yourFile.txt");
BufferedReader br = new BufferedReader(fr);
String curLine = br.next();
while(curLine!=null)
{
String[] tempLine = curLine.split(" ");
int threat = Integer.parseInt(tempLine[0]);
String user = tempLine[1];
long ID = Long.parseLong(tempLine[2]);
addPOI(ID,user,threat);
}
The addPOI method would look something like this.
public void addPOI(long ID, String user, int threatLevel)
{
list.addAtLast(new POI(ID,user,threadLevel));
}
And the list can be declared something like this,
List<POI> list = new List<POI>();
Greeting to everyone. I currently work on a program that sorting the emergency number of patients(the number that assigned by nurse when they enter the emergency room and this number determines the seriousness of their sickness too). However, if there are more than 1 patient who hold the same emergency numbers(eg: 2 patients hold emergency number 1), the one who came earlier should receive the treatment first. For this reason, I have 2 sortings, one is to sort the emergency number in ascending order and the other is to sort the time in ascending order too. But unfortunately the second sorting cannot work correctly.The following are the explanations for the type of emergency numbers:
Emergency number : 1 – Immediately life threatening
Emergency number : 2 – Urgent, but not immediately life threatening
Emergency number : 3 – Less urgent
So,now comes the coding part(Please note that this is a linkedlist)
Interface:
public interface ListInterface<T> {
public boolean add(T newEntry);
public boolean add(int newPosition, T newEntry);
public T remove(int givenPosition);
public void clear();
public boolean replace(int givenPosition, T newEntry);
public T getEntry(int givenPosition);
public boolean contains(T anEntry);
public int getLength();
public boolean isEmpty();
public boolean isFull();
}
LList class:
/**
* LList.java
* A class that implements the ADT list by using a chain of nodes,
* with the node implemented as an inner class.
*/
public class LList<T> implements ListInterface<T> {
private Node firstNode; // reference to first node
private int length; // number of entries in list
public LList() {
clear();
}
public final void clear() {
firstNode = null;
length = 0;
}
public boolean add(T newEntry) {
Node newNode = new Node(newEntry); // create the new node
if (isEmpty()) // if empty list
firstNode = newNode;
else { // add to end of nonempty list
Node currentNode = firstNode; // traverse linked list with p pointing to the current node
while (currentNode.next != null) { // while have not reached the last node
currentNode = currentNode.next;
}
currentNode.next = newNode; // make last node reference new node
}
length++;
return true;
}
public boolean add(int newPosition, T newEntry) { // OutOfMemoryError possible
boolean isSuccessful = true;
if ((newPosition >= 1) && (newPosition <= length+1)) {
Node newNode = new Node(newEntry);
if (isEmpty() || (newPosition == 1)) { // case 1: add to beginning of list
newNode.next = firstNode;
firstNode = newNode;
}
else { // case 2: list is not empty and newPosition > 1
Node nodeBefore = firstNode;
for (int i = 1; i < newPosition - 1; ++i) {
nodeBefore = nodeBefore.next; // advance nodeBefore to its next node
}
newNode.next = nodeBefore.next; // make new node point to current node at newPosition
nodeBefore.next = newNode; // make the node before point to the new node
}
length++;
}
else
isSuccessful = false;
return isSuccessful;
}
public T remove(int givenPosition) {
T result = null; // return value
if ((givenPosition >= 1) && (givenPosition <= length)) {
if (givenPosition == 1) { // case 1: remove first entry
result = firstNode.data; // save entry to be removed
firstNode = firstNode.next;
}
else { // case 2: givenPosition > 1
Node nodeBefore = firstNode;
for (int i = 1; i < givenPosition - 1; ++i) {
nodeBefore = nodeBefore.next; // advance nodeBefore to its next node
}
result = nodeBefore.next.data; // save entry to be removed
nodeBefore.next = nodeBefore.next.next; // make node before point to node after the
} // one to be deleted (to disconnect node from chain)
length--;
}
return result; // return removed entry, or
// null if operation fails
}
public boolean replace(int givenPosition, T newEntry) {
boolean isSuccessful = true;
if ((givenPosition >= 1) && (givenPosition <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < givenPosition - 1; ++i) {
// System.out.println("Trace| currentNode.data = " + currentNode.data + "\t, i = " + i);
currentNode = currentNode.next; // advance currentNode to next node
}
currentNode.data = newEntry; // currentNode is pointing to the node at givenPosition
}
else
isSuccessful = false;
return isSuccessful;
}
public T getEntry(int givenPosition) {
T result = null;
if ((givenPosition >= 1) && (givenPosition <= length)) {
Node currentNode = firstNode;
for (int i = 0; i < givenPosition - 1; ++i) {
currentNode = currentNode.next; // advance currentNode to next node
}
result = currentNode.data; // currentNode is pointing to the node at givenPosition
}
return result;
}
public boolean contains(T anEntry) {
boolean found = false;
Node currentNode = firstNode;
while (!found && (currentNode != null)) {
if (anEntry.equals(currentNode.data))
found = true;
else
currentNode = currentNode.next;
}
return found;
}
public int getLength() {
return length;
}
public boolean isEmpty() {
boolean result;
if (length == 0)
result = true;
else
result = false;
return result;
}
public boolean isFull() {
return false;
}
public String toString() {
String outputStr = "";
Node currentNode = firstNode;
while (currentNode != null) {
outputStr += currentNode.data + "\n";
currentNode = currentNode.next;
}
return outputStr;
}
private class Node {
private T data;
private Node next;
private Node(T data) {
this.data = data;
this.next = null;
}
private Node(T data, Node next) {
this.data = data;
this.next = next;
}
} // end Node
} // end LList
Patient class:
public class Patient {
private int emergencyNo;
private int queueTime;
private String patientName;
private String patientIC;
private String patientGender;
private String patientTelNo;
private String patientAdd;
private String visitDate;
public Patient() {
}
public Patient(int emergencyNo, int queueTime, String patientName, String patientIC, String patientGender, String patientTelNo, String patientAdd, String visitDate)
{
this.emergencyNo = emergencyNo;
this.queueTime = queueTime;
this.patientName = patientName;
this.patientIC = patientIC;
this.patientGender = patientGender;
this.patientTelNo = patientTelNo;
this.patientAdd = patientAdd;
this.visitDate = visitDate;
}
//set methods
public void setQueueTime(int queueTime)
{
this.queueTime = queueTime;
}
public boolean setEmergencyNo(int emergencyNo)
{
boolean varEmergencyNo = true;
if (emergencyNo != 1 && emergencyNo != 2 && emergencyNo != 3)
{
varEmergencyNo = false;
System.out.println("Emergency number is in invalid format!");
System.out.println("Emergency number is either 1, 2 or 3 only!");
System.out.println("\n");
}
else
{
this.emergencyNo = emergencyNo;
}
return varEmergencyNo;
}
public boolean setPatientName(String patientName)
{
boolean varPatientName = true;
if (patientName.equals("") || patientName.equals(null))
{
varPatientName = false;
System.out.println("The patient name cannot be empty!\n");
}
else
{
this.patientName = patientName;
}
return varPatientName;
}
public boolean setPatientIC(String patientIC)
{
boolean varPatientIC = true;
if(!patientIC.matches("^[0-9]{12}$"))
{
varPatientIC = false;
System.out.println("IC is in invalid format!");
System.out.println("It must consist of 12 numbers only!\n");
}
else
{
this.patientIC = patientIC;
}
return varPatientIC;
}
public boolean setPatientGender(String patientGender)
{
boolean varPatientGender = true;
if(!patientGender.equals("F") && !patientGender.equals("f") && !patientGender.equals("M") && !patientGender.equals("m"))
{
varPatientGender = false;
System.out.println("Gender is in invalid format!");
System.out.println("It must be either 'M' or 'F' only!\n");
}
else
{
this.patientGender = patientGender;
}
return varPatientGender;
}
public boolean setPatientTelNo(String patientTelNo)
{
boolean varPatientTelNo = true;
if((!patientTelNo.matches("^01[02346789]\\d{7}$")) && (!patientTelNo.matches("^03\\d{8}$")))
{
varPatientTelNo = false;
System.out.println("Invalid phone number!");
System.out.println("It must be in the following format : 0167890990 / 0342346789!\n");
System.out.print("\n");
}
else
{
this.patientTelNo = patientTelNo;
}
return varPatientTelNo;
}
public boolean setPatientAdd(String patientAdd)
{
boolean varPatientAdd = true;
if (patientAdd.equals("") || patientAdd.equals(null))
{
varPatientAdd = false;
System.out.println("The patient address cannot be empty!\n");
}
else
{
this.patientAdd = patientAdd;
}
return varPatientAdd;
}
public void setVisitDate(String visitDate)
{
this.visitDate = visitDate;
}
//get methods
public int getQueueTime()
{
return this.queueTime;
}
public int getEmergencyNo()
{
return this.emergencyNo;
}
public String getPatientName()
{
return this.patientName;
}
public String getPatientIC()
{
return this.patientIC;
}
public String getPatientGender()
{
return this.patientGender;
}
public String getPatientTelNo()
{
return this.patientTelNo;
}
public String getPatientAdd()
{
return this.patientAdd;
}
public String getVisitDate()
{
return this.visitDate;
}
#Override
public String toString()
{
return (this.emergencyNo + "\t\t" + this.patientName + "\t\t" + this.patientIC +
"\t\t" + this.patientGender + "\t\t" + this.patientTelNo + "\t\t" + this.patientAdd + "\t\t" + this.visitDate);
}
public String anotherToString()
{
return (this.emergencyNo + "\t\t\t\t\t\t" + this.patientName + "\t\t\t " + this.visitDate);
}
}
EmergencyCmp(Comparator)--->use for sorting the emergency numbers of the patients
import java.util.Comparator;
public class EmergencyCmp implements Comparator<Patient>
{
#Override
public int compare(Patient p1, Patient p2)
{
if(p1.getEmergencyNo() > p2.getEmergencyNo())
{
return 1;
}
else
{
return -1;
}
}
}
QueueCmp(Comparator)--->use for sorting the arrival time of the patients
import java.util.Comparator;
public class QueueCmp implements Comparator<Patient>
{
#Override
public int compare(Patient p1, Patient p2)
{
if(p1.getQueueTime() > p2.getQueueTime())
{
return 1;
}
else
{
return -1;
}
}
}
Main function:
import java.util.Calendar;
import java.util.Scanner;
import java.util.Arrays;
import java.util.*;
public class DSA {
public DSA() {
}
public static void main(String[] args) {
//patient's attributes
int emergencyNo;
int queueTime;
String patientName;
String patientIC;
String patientGender;
String patientTelNo;
String patientAdd;
String visitDate;
//counter
int j = 0;
int x = 0;
int y = 0;
int z = 0;
int count1 = 0;
int count2 = 0;
int count3 = 0;
int countEnteredPatient = 1;
int totalCount = 0;
//calendar
int nowYr, nowMn, nowDy, nowHr, nowMt, nowSc;
//others
boolean enterNewPatient = true;
String continueInput;
boolean enterNewPatient1 = true;
String continueInput1;
boolean continueEmergencyNo;
Scanner scan = new Scanner(System.in);
ListInterface<Patient> patientList = new LList<Patient>();
ListInterface<Patient> newPatientList = new LList<Patient>();
Patient[] patientArr1 = new Patient[10000];
Patient[] patientArr2 = new Patient[10000];
Patient[] patientArr3 = new Patient[10000];
Patient tempoPatient;
do{
//do-while loop for entering new patient details after viewing patient list
System.out.println("Welcome to Hospital Ten Stars!\n");
do{
//do-while loop for entering new patient details
System.out.println("Entering details of patient " + countEnteredPatient);
System.out.println("===================================\n");
Calendar calendar = Calendar.getInstance();
nowYr = calendar.get(Calendar.YEAR);
nowMn = calendar.get(Calendar.MONTH);
nowDy = calendar.get(Calendar.DAY_OF_MONTH);
nowHr = calendar.get(Calendar.HOUR);
nowMt = calendar.get(Calendar.MINUTE);
nowSc = calendar.get(Calendar.SECOND);
queueTime = calendar.get(Calendar.MILLISECOND);
visitDate = nowDy + "/" + nowMn + "/" + nowYr + ", " + nowHr + ":" + nowMt + ":" + nowSc;
//input emergency number
do{
tempoPatient = new Patient();
continueEmergencyNo = false;
int EmergencyNoOption;
try
{
do{
System.out.print("Please select 1 – Immediately life threatening, 2 – Urgent, but not immediately life threatening or 3 – Less urgent(Eg: 1) : ");
EmergencyNoOption = scan.nextInt();
scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setEmergencyNo(EmergencyNoOption) == false);
}
catch(InputMismatchException ex)
{
System.out.print("\n");
System.out.println("Invalid input detected.");
scan.nextLine();
System.out.print("\n");
continueEmergencyNo = true;
}
}while(continueEmergencyNo);
//input patient name
do{
System.out.print("Patient name(Eg: Christine Redfield) : ");
patientName = scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setPatientName(patientName) == false);
//input patient ic no
do{
System.out.print("Patient IC number(Eg: 931231124567) : ");
patientIC = scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setPatientIC(patientIC) == false);
//input patient gender
do{
System.out.print("Patient gender(Eg: M) : ");
patientGender = scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setPatientGender(patientGender) == false);
//input patient tel. no
do{
System.out.print("Patient tel.No(without'-')(Eg: 0162345678/0342980123) : ");
patientTelNo = scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setPatientTelNo(patientTelNo) == false);
//input patient address
do{
System.out.print("Patient address(Eg: 4-C9 Jln Besar 123, Taman Besar, 56000 Kuala Lumpur) : ");
patientAdd = scan.nextLine();
System.out.print("\n");
}while(tempoPatient.setPatientAdd(patientAdd) == false);
tempoPatient.setQueueTime(queueTime);
tempoPatient.setVisitDate(visitDate);
patientList.add(tempoPatient);
//decide whether want to enter a new patient or not
do{
System.out.print("Do you want to enter another new patient?(Eg: Y/N) : ");
continueInput = scan.nextLine();
if(continueInput.equals("Y") || continueInput.equals("y"))
{
enterNewPatient = true;
System.out.print("\n");
}
else if(continueInput.equals("N") || continueInput.equals("n"))
{
enterNewPatient = false;
}
else
{
System.out.println("\n");
System.out.println("Please enter Y/N only.\n");
}
}while(!continueInput.equals("Y") && !continueInput.equals("y") && !continueInput.equals("N") && !continueInput.equals("n"));
countEnteredPatient++;
}while(enterNewPatient); //end do-while loop for entering new patient details
System.out.println("\nWaiting list of patient will be displayed soon.\n");
try{
Thread.sleep(1000);
}
catch (Exception e)
{
}
System.out.println("Waiting list of patients");
System.out.println("========================\n");
System.out.println("Number\t\tEmergency number\t\tPatient name\t\t ArrivalTime");
System.out.println("============================================================================");
for(int i = 1; i <= patientList.getLength(); i++)
{
System.out.println(i + "\t\t\t" + patientList.getEntry(i).anotherToString());
}
do{
System.out.print("\nSo, now do you want to enter another new patient?(Eg: Y/N) : ");
continueInput1 = scan.nextLine();
if(continueInput1.equals("Y") || continueInput1.equals("y"))
{
enterNewPatient1 = true;
System.out.print("\n");
}
else if(continueInput1.equals("N") || continueInput1.equals("n"))
{
enterNewPatient1 = false;
}
else
{
System.out.println("\n");
System.out.println("Please enter Y/N only.\n");
}
}while(!continueInput1.equals("Y") && !continueInput1.equals("y") && !continueInput1.equals("N") && !continueInput1.equals("n"));
}while(enterNewPatient1);//end do-while loop for entering new patient details after viewing patient list
System.out.println("\nNow rearranging the list based on the seriouness and their arrival time.");
try{
Thread.sleep(1000);
}
catch (Exception e)
{
}
//create an unsorted array
Patient[] tempoPatientArr = new Patient[patientList.getLength()];
//copy the contents of patientList into tempoPatientArr
for(int i = 1; i <= patientList.getLength(); i++ )
{
tempoPatientArr[i-1] = patientList.getEntry(i);
}
//sort tempoPatientArr
Arrays.sort(tempoPatientArr, new EmergencyCmp());
//the above part until this comment line does not have problem
//check the emergency no and then categorise accordingly
for(int i = 0; i < tempoPatientArr.length; i++)
{
if(tempoPatientArr[i].getEmergencyNo() == 1)
{
patientArr1[x] = tempoPatientArr[i];
x++;
}
else if(tempoPatientArr[i].getEmergencyNo() == 2)
{
patientArr2[y] = tempoPatientArr[i];
y++;
}
else if(tempoPatientArr[i].getEmergencyNo() == 3)
{
patientArr3[z] = tempoPatientArr[i];
z++;
}
}
//to check how many !null elements by using count for 3 sub-arrays
for(int i = 0; i < patientArr1.length; i++)
{
if(patientArr1[i] != null)
{
count1++;
}
else
{
break;
}
}
for(int i = 0; i < patientArr2.length; i++)
{
if(patientArr2[i] != null)
{
count2++;
}
else
{
break;
}
}
for(int i = 0; i < patientArr3.length; i++)
{
if(patientArr3[i] != null)
{
count3++;
}
else
{
break;
}
}
//new array with elimination of null values
Patient[] newPatientArr1 = new Patient[count1];
Patient[] newPatientArr2 = new Patient[count2];
Patient[] newPatientArr3 = new Patient[count3];
//copy the contents of old sub arrays(the arrays with null values) into the new sub arrays(without null values)
for(int i = 0; i < newPatientArr1.length; i++)
{
newPatientArr1[i] = patientArr1[i];
}
for(int i = 0; i < newPatientArr2.length; i++)
{
newPatientArr2[i] = patientArr2[i];
}
for(int i = 0; i < newPatientArr3.length; i++)
{
newPatientArr3[i] = patientArr3[i];
}
totalCount = count1 + count2 + count3;
//array that used to combine all the sub-arrays
Patient[] newPatientArr = new Patient[totalCount];
//sort all sub new arrays
Arrays.sort(newPatientArr1, new QueueCmp());
Arrays.sort(newPatientArr2, new QueueCmp());
Arrays.sort(newPatientArr3, new QueueCmp());
//combine the contents of sub new arrays into the newPatientArr array
do{
for (int i = 0; i < count1; i++)
{
newPatientArr[j] = newPatientArr1[i];
j++;
}
for (int b = 0; b < count2; b++)
{
newPatientArr[j] = newPatientArr2[b];
j++;
}
for (int c = 0; c < count3; c++)
{
newPatientArr[j] = newPatientArr3[c];
j++;
}
}while(j < totalCount);
//relink the nodes
for(int i = 0; i < newPatientArr.length; i++)
{
newPatientList.add(newPatientArr[i]);
}
System.out.println("\nSorted waiting list of patients");
System.out.println("===============================\n");
System.out.println("Number\t\tEmergency number\t\tPatient name\t\t ArrivalTime");
System.out.println("============================================================================");
for(int i = 1; i <= newPatientList.getLength(); i++)
{
System.out.println(i + "\t\t\t" + newPatientList.getEntry(i).anotherToString());
}
}
}
Interface and LList class definitely do not have problems. So everyone can skip the 2 parts.
For the main function, I have a comment like this:
//the above part until this comment line does not have problem
When you all see the comment, that means the previous code does not have problem and you all may skip it and below is an attachment of the result that I got earlier:
So, from the picture you all can see that the sorting of arrival time is not correct. I hope that I can know why does this problem occurs since I cannot figure it out by myself. Thanks to all of you first.
So, after taking the advice of #Scott Hunter, I have made the following modification to the EmergencyCmp:
#Override
public int compare(Patient p1, Patient p2)
{
int value = 0;
if(p1.getEmergencyNo() > p2.getEmergencyNo())
{
value = 1;
}
else if(p1.getEmergencyNo() < p2.getEmergencyNo())
{
value = -1;
}
else if(p1.getEmergencyNo() == p2.getEmergencyNo())
{
if(p1.getQueueTime() > p2.getQueueTime())
{
return 1;
}
else
{
return -1;
}
}
return value;
}
However, the time sorting still produce a wrong result.
As I understand it (which I may not; you provided a LOT of extraneous stuff), it looks like you are trying to perform 2 distinct sorts, one after the other, such that the second is undoing the work of the first. Instead, you should define a single Comparator which compares emergency numbers and, only if they are the same, compares arrival times.
I'm supposed to order the numbers inserted in this list. I have to order it backwards too. I've been trying to do it for the last couple of hours but I haven't come up with anything. I'm a beginner and to me the hardest part is to order it using of its pointers.
public class MyList {
private static class MyList
{
public int num;
public MyList nextn;
}
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
MyList start = null;
MyList end = null;
MyList aux;
MyList before;
int op, number, found;
do{
System.out.println("1- insert number in the beginning list");
System.out.println("2- insert in the end of the list");
System.out.println("3- query list");
System.out.println("4- remove from list");
System.out.println("5- empty list");
System.out.println("6- exit");
System.out.print("choose: ");
op = input.nextInt();
if(op < 1||op>6)
{
System.out.println("invalid number");
}
if(op == 1)
{
System.out.println("type the number to be inserted in the beginning of the list");
MyList newl = new MyList();
newl.num = input.nextInt();
if(start == null)
{
start = newl;
end = newl;
newl.nextn = null;
}
else
{
newl.nextn = start;
start = newl;
}
System.out.println("number inserted");
}
if(op == 2)
{
System.out.println("type the number to be inserted in the end of the list");
MyList newl = new MyList();
newl.num = input.nextInt();
if(start == null)
{
start = newl;
end = newl;
newl.nextn = null;
}
else
{
end.nextn = newl;
end = newl;
newl.nextn = null;
}
System.out.println("number inserted");
}
if(op == 3)
{
if(start == null)
{
System.out.println("list is empty");
}
else
{ System.out.println("\nquerying the list\n");
aux = start;
while(aux!=null)
{
System.out.print(aux.num+ " ");
aux = aux.nextn;
}
}
}
if(op == 4)
{
if(start == null)
{
System.out.println("list is empty");
}
else
{
System.out.println("\ntype the number to be removed:\n");
number = input.nextInt();
aux = start;
before = null;
found = 0;
while(aux!=null)
{
if(aux.num == number)
{
found = found +1;
if(aux == start)
{
start = aux.nextn;
aux = start;
}
else if(aux == end)
{
before.nextn = null;
end = before;
aux = null;
}
else
{
before.nextn =aux.nextn;
aux = aux.nextn;
}
}
else
{
before = aux;
aux =aux.nextn;
}
}
if(found ==0) {
System.out.append("number not found");
}
else if(found ==1)
{
System.out.append("number removed once!");
}
else
{
System.out.append("number removed "+found+" times!");
}
}
}
if(op == 5)
{
if(start == null)
{
System.out.println("empty list");
}
else
{
start = null;
System.out.println("emptied list");
}
}
} while(op !=6);
}
First - do something with your naming conventions.
You have two classes with the same name MyList (one is public, one is Inner). That's why I suggest changing the Inners class name to MyListElement:
private class MyListElement
{
private final Integer value;
private MyListElement nextElement;
private MyListElement(final Integer value)
{
this.value = value;
}
}
No more nextn or num. List elements have values and nextElements. Also - their values are final (cannot be changed). No more start, op, found, aux and so on. Those names mean **** and are not helpful, and are messing up the code.
Second - don't do everything in a main method.
It's bad practice. It forces you to use static fields and methods. Create an object in main method and let that object do the work for you:
public class MyList
{
private Scanner userInput;
private Integer selectedOption;
private MyListElement firstElement = null;
private boolean exitRequested = false;
public static void main(final String[] args)
{
MyList myList = new MyList(new Scanner(System.in));
myList.run();
}
private MyList(final Scanner userInput)
{
this.userInput = userInput;
}
//other methods and classes
}
Third - how should your code work?
As simple as possible. That said:
public void run()
{
do
{
promptUserForOperation();
processSelectedOperation();
} while(!exitRequested);
}
Simple enough?
Fourth - You know how to prompt. How to process?
Again - as simple as possible. That said:
private void processSelectedOption()
{
switch (selectedOption)
{
case 1:
case 2:
{
addNewElement();
} break;
case 3:
{
printList();
} break;
case 4:
{
removeElement();
} break;
case 5:
{
clearList();
} break;
case 6:
{
exit();
} break;
default:
{
printWrongOperationSelected();
}
}
}
Finally - how to sort?
private void addNewElement()
{
//getting the input
System.out.print("Please type the number to be added to the list: ");
Integer newValue = null;
while(newValue == null)
{
try
{
newValue = Integer.parseInt(userInput.nextLine());
}
catch (final Exception e)
{
System.out.println("Wrong value. Please insert new value.");
}
}
//creating new element based on the input
MyListElement newElement = new MyListElement(newValue);
//if not first
if (firstElement != null)
{
placeElementInList(newElement);
}
else
{
firstElement = newElement; //if first
}
}
//if not first
private void placeElementInList(final MyListElement newElement)
{
//if smaller than first
if (newElement.value < firstElement.value)
{
newElement.nextElement = firstElement; //new points to first
firstElement = newElement; //and becomes first
}
else
{
MyListElement previousElement = firstElement; //have to remember previous element
MyListElement elementInList = firstElement.nextElement; //currently checked.
while (elementInList != null)
{
if (newElement.value < elementInList.value) //if new element is smaller that currently checked
{
break; //break - put it in current position.
}
previousElement = elementInList; //if not, move forward, substitute variables
elementInList = elementInList.nextElement;
}
previousElement.nextElement = newElement; //set the new element at the proper position
newElement.nextElement = elementInList; //
}
}
The remove method is almost the same.
And that's all.
You can do it you're way - using the sorting method presented - but I'd suggest learning good habbits as soon as possible. And that is naming your classes/methods/fields/variables properly (they don't have to be short, use ctrl+space), and fragmenting the code to the smallest parts possible. Mind that the above code is far from being perfect - much can be improved.
SPOILER
Whole (working) code:
package test;
import java.util.Scanner;
public class MyList
{
private Scanner userInput;
private Integer selectedOption;
private MyListElement firstElement = null;
private boolean exitRequested = false;
public static void main(final String[] args)
{
new MyList(new Scanner(System.in)).run();
}
private MyList(final Scanner userInput)
{
this.userInput = userInput;
}
public void run()
{
do
{
promptUserForOption();
processSelectedOption();
} while(!exitRequested);
}
private void promptUserForOption()
{
System.out.println("");
System.out.println("1 - insert number in the beginning list");
System.out.println("2 - insert in the end of the list");
System.out.println("3 - query list");
System.out.println("4 - remove from list");
System.out.println("5 - empty list");
System.out.println("6 - exit");
System.out.print("Please choose option: ");
try
{
selectedOption = Integer.parseInt(userInput.nextLine());
}
catch (final Exception e)
{
printWrongOperationSelected();
selectedOption = -1;
}
}
private void printWrongOperationSelected()
{
System.out.println("Wrong operation selected.");
}
private void processSelectedOption()
{
switch (selectedOption)
{
case 1:
case 2:
{
addNewElement();
} break;
case 3:
{
printList();
} break;
case 4:
{
removeElement();
} break;
case 5:
{
clearList();
} break;
case 6:
{
exit();
} break;
default:
{
printWrongOperationSelected();
}
}
}
private void addNewElement()
{
System.out.print("Please type the number to be added to the list: ");
Integer newValue = null;
while(newValue == null)
{
try
{
newValue = Integer.parseInt(userInput.nextLine());
}
catch (final Exception e)
{
System.out.println("Wrong value. Please insert new value.");
}
}
MyListElement newElement = new MyListElement(newValue);
if (firstElement != null)
{
placeElementInList(newElement);
}
else
{
firstElement = newElement;
}
}
private void placeElementInList(final MyListElement newElement)
{
if (newElement.value < firstElement.value)
{
newElement.nextElement = firstElement;
firstElement = newElement;
}
else
{
MyListElement previousElement = firstElement;
MyListElement elementInList = firstElement.nextElement;
while (elementInList != null)
{
if (newElement.value < elementInList.value)
{
break;
}
previousElement = elementInList;
elementInList = elementInList.nextElement;
}
previousElement.nextElement = newElement;
newElement.nextElement = elementInList;
}
}
private void printList()
{
if (firstElement == null)
{
System.out.println("No elements in the list.");
}
else
{
MyListElement elementInList = firstElement;
while (elementInList != null)
{
System.out.print(elementInList.value + ", ");
elementInList = elementInList.nextElement;
}
System.out.println("");
}
}
private void removeElement()
{
System.out.print("Please type the number to be removed from the list: ");
Integer valueToRemove = null;
while(valueToRemove == null)
{
try
{
valueToRemove = Integer.parseInt(userInput.nextLine());
}
catch (final Exception e)
{
System.out.println("Wrong value. Please insert value to remove.");
}
}
if (firstElement == null)
{
System.out.println("No elements in the list. None can be removed.");
}
else
{
boolean found = false;
if (firstElement.value.equals(valueToRemove))
{
firstElement = firstElement.nextElement;
found = true;
}
else
{
MyListElement previousElement = firstElement;
MyListElement elementInList = firstElement.nextElement;
while (elementInList != null)
{
if (elementInList.value.equals(valueToRemove))
{
previousElement.nextElement = elementInList.nextElement;
found = true;
break;
}
previousElement = elementInList;
elementInList = elementInList.nextElement;
}
}
if (!found)
{
System.out.println("Value " + valueToRemove + " is not in the list.");
return;
}
else
{
System.out.println("Value removed.");
}
}
}
private void clearList()
{
firstElement = null;
}
private void exit()
{
exitRequested = true;
}
private class MyListElement
{
private final Integer value;
private MyListElement nextElement;
private MyListElement(final Integer value)
{
this.value = value;
}
}
}
EDIT(from Phone)
private void printInReverse()
{
MyListElement tmpElement=firstElement;
MyListElement previousElement=tmpElement.nextElement;
while (previousElement!=null)
{
previousElement.nextElement=tmpElement;
tmpElement =previousElement;
previousElement=previousElenent.nextElement;
}
MyListElement firstReverseElement=tmpElement;
//loop like in the normal print loop but using firstReverseElement as starting point. You can create print methodthat would take First element as param.
}
EDIT - REVERSE ORDER COMPLETE:
private void printList()
{
printListFromElement(firstElement);
}
private void printListFromElement(final MyListElement firstElementToPrint)
{
if (firstElementToPrint == null)
{
System.out.println("No elements in the list.");
}
else
{
MyListElement elementInList = firstElementToPrint;
while (elementInList != null)
{
System.out.print(elementInList.value + ", ");
elementInList = elementInList.nextElement;
}
System.out.println("");
}
}
private void printListInReverse()
{
if (firstElement == null)
{
System.out.println("No elements in the list.");
}
else
{
MyListElement fistElementInReverse = new MyListElement(firstElement.value);
MyListElement previousElement;
MyListElement elementInOriginalList = firstElement;
while (elementInOriginalList.nextElement != null)
{
previousElement = fistElementInReverse;
fistElementInReverse = new MyListElement(elementInOriginalList.nextElement.value);
fistElementInReverse.nextElement = previousElement;
elementInOriginalList = elementInOriginalList.nextElement;
}
printListFromElement(fistElementInReverse);
}
}
Here in the reversing loop you have to create new MyListElementObjects. You get infinite loop/break original list/get null pointer if you don't do that, as you only change references in the original list.
I have a project which is to “Start with the tree.java program (Listing 8.1) and modify it to create a binary
tree from a string of letters (like A, B, and so on) entered by the user. Each
letter will be displayed in its own node. Construct the tree so that all the nodes
that contain letters are leaves. Parent nodes can contain some non-letter
symbol like +. Make sure that every parent node has exactly two children.
Don’t worry if the tree is unbalanced.” The book gives us a hint on how to begin. “One way to begin is by making an array of trees. (A group of unconnected trees
is called a forest.) Take each letter typed by the user and put it in a node. Take
each of these nodes and put it in a tree, where it will be the root. Now put all
these one-node trees in the array. Start by making a new tree with + at the root
and two of the one-node trees as its children. Then keep adding one-node trees
from the array to this larger tree. Don’t worry if it’s an unbalanced tree.”
import java.io.*;
import java.util.*;
class Node
{
public String iData; // data item (key)
public Node leftChild; // this node’s left child
public Node rightChild; // this node’s right child
public void displayNode() // display ourself
{
System.out.print('{');
System.out.print(iData);
System.out.print("} ");
}
} // end class Node
class Tree
{
private Node root; // first node of tree
public void setNode(Node newNode)
{root = newNode;}
public Node getNode()
{return root;}
// -------------------------------------------------------------
public Tree() // constructor
{ root = null; } // no nodes in tree yet
// -------------------------------------------------------------
public void traverse(int traverseType)
{
switch(traverseType)
{
case 1: System.out.print("nPreorder traversal: ");
preOrder(root);
break;
case 2: System.out.print("nInorder traversal: ");
inOrder(root);
break;
case 3: System.out.print("nPostorder traversal: ");
postOrder(root);
break;
}
System.out.println();
}
private void preOrder(Node localRoot)
{
if(localRoot != null)
{
System.out.print(localRoot.iData + " ");
preOrder(localRoot.leftChild);
preOrder(localRoot.rightChild);
}
}
// -------------------------------------------------------------
private void inOrder(Node localRoot)
{
if(localRoot != null)
{
inOrder(localRoot.leftChild);
System.out.print(localRoot.iData + " ");
inOrder(localRoot.rightChild);
}
}
// -------------------------------------------------------------
private void postOrder(Node localRoot)
{
if(localRoot != null)
{
postOrder(localRoot.leftChild);
postOrder(localRoot.rightChild);
System.out.print(localRoot.iData + " ");
}
}
// -------------------------------------------------------------
public void displayTree()
{
Stack globalStack = new Stack();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println(
"......................................................");
while(isRowEmpty==false)
{
Stack localStack = new Stack();
isRowEmpty = true;
for(int j=0; j<nBlanks; j++)
System.out.print(' ');
while(globalStack.isEmpty()==false)
{
Node temp = (Node)globalStack.pop();
if(temp != null)
{
System.out.print(temp.iData);
localStack.push(temp.leftChild);
localStack.push(temp.rightChild);
if(temp.leftChild != null ||
temp.rightChild != null)
isRowEmpty = false;
}
else
{
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for(int j=0; j<nBlanks*2-2; j++)
System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while(localStack.isEmpty()==false)
globalStack.push( localStack.pop() );
} // end while isRowEmpty is false
System.out.println(
"......................................................");
} // end displayTree()
// -------------------------------------------------------------
}
public class Leaves
{
//function used to enter the single node trees into a larger tree
public static void enterLetters(Node localRoot, Tree[] nodeTree, int i)
{
if(localRoot != null && i == nodeTree.length)
{
if(nodeTree.length == i - 1)
{
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
else
{
Node plusNode = new Node();
plusNode.iData = "+";
localRoot.leftChild = plusNode;
localRoot.rightChild = nodeTree[i].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
}
}
public static void main(String[] args)
{
Tree[] forest = new Tree[10];
Scanner sc = new Scanner(System.in);
for(int i = 0; i < 10; i++)
{
String letter;
forest[i] = new Tree();
System.out.println("Enter a letter: ");
letter = sc.nextLine();
Node newNode = new Node();
newNode.iData = letter;
forest[i].setNode(newNode);
}
Tree letterTree = new Tree();
Node firstNode = new Node();
firstNode.iData = "+";
letterTree.setNode(firstNode);
enterLetters(letterTree.getNode(), forest, 0);
letterTree.displayTree();
}
}
My problem is trying to get the array of single node trees into the larger tree. I tried making a recursive function but when I display the larger tree it only shows the first node and it is as if the function enterLeaves never did it’s job.
This can't be correct:
public static void enterLetters(Node localRoot, Tree[] nodeTree, int i) {
if (localRoot != null && i == nodeTree.length) {
if (nodeTree.length == i - 1) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
} else {
Node plusNode = new Node();
plusNode.iData = "+";
localRoot.leftChild = plusNode;
localRoot.rightChild = nodeTree[i].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
}
}
When you enter this method: localRoot != null, i == 0, and nodeTree.length==10
So the if statement is failing. I am guess the if statement should read:
if (localRoot != null && i < nodeTree.length)
Also, I am pretty sure your second if statement is incorrect also; I believe it should be.
if (nodeTree.length-2 == i) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
return;
}
Instead of:
if (nodeTree.length == i - 1) {
localRoot.leftChild = nodeTree[i].getNode();
localRoot.rightChild = nodeTree[i + 1].getNode();
enterLetters(localRoot.leftChild, nodeTree, i + 1);
}
You want to stop when you have two Nodes left to process (nodeTree.length-2 == i) and after you do that you should return instead of entering the remaining letters.
Here's what I came up with that works:
Node.java
/** Represents a node in a binary tree data structure */
public class Node {
private char letter;
private Node leftChild;
private Node rightChild;
public Node(char letter) {
this.letter = letter;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
public Node getRightChild() {
return rightChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getLeftChild() {
return leftChild;
}
/** Returns a String representation of this node. */
#Override
public String toString() {
return "" + letter;
}
}
Tree.java
import java.util.Stack;
/**
* A binary tree
*/
public class Tree {
private Node root;
public void setRoot(Node root) {
this.root = root;
}
public void addToLeft(Node node) {
root.setLeftChild(node);
}
public void addToRight(Node node) {
root.setRightChild(node);
}
public Node getRoot() {
return root;
}
public void displayTree() {
Stack<Node> globalStack = new Stack<>();
globalStack.push(root);
int nBlanks = 32;
boolean isRowEmpty = false;
System.out.println(
"......................................................");
while (!isRowEmpty) {
Stack<Node> localStack = new Stack<>();
isRowEmpty = true;
for (int j = 0; j < nBlanks; j++)
System.out.print(' ');
while (!globalStack.isEmpty()) {
Node temp = (Node) globalStack.pop();
if (temp != null) {
System.out.print(temp);
localStack.push(temp.getLeftChild());
localStack.push(temp.getRightChild());
if (temp.getLeftChild() != null ||
temp.getRightChild() != null)
isRowEmpty = false;
} else {
System.out.print("--");
localStack.push(null);
localStack.push(null);
}
for (int j = 0; j < nBlanks * 2 - 2; j++)
System.out.print(' ');
} // end while globalStack not empty
System.out.println();
nBlanks /= 2;
while (!localStack.isEmpty())
globalStack.push(localStack.pop());
} // end while isRowEmpty is false
System.out.println(
"......................................................");
}
}
Forest.java
/**
* A collection of OneNodeTrees combined together in one tree
*/
public class Forest {
private Tree[] forest;
private int forestIndex;
public Forest(int numTrees) {
forest = new Tree[numTrees];
forestIndex = 0;
}
public boolean add(Tree tree) {
if(forestIndex < forest.length) {
forest[forestIndex++] = tree;
return true;
} else {
return false;
}
}
public Tree createMainTree() {
Tree firstTree = new Tree();
firstTree.setRoot(new Node('+'));
firstTree.addToLeft(forest[0].getRoot());
firstTree.addToRight(forest[1].getRoot());
forest[1] = firstTree;
int mainTreeIndex = 0;
Tree tempTree;
for(mainTreeIndex = 2; mainTreeIndex < forest.length; mainTreeIndex++) {
tempTree = new Tree();
tempTree.setRoot(new Node('+'));
tempTree.addToLeft(forest[mainTreeIndex - 1].getRoot());
tempTree.addToRight(forest[mainTreeIndex].getRoot());
forest[mainTreeIndex] = tempTree;
}
return forest[mainTreeIndex - 1];
}
public static void main(String[] args) {
final int numberOfTrees = 6;
Forest forest = new Forest(numberOfTrees);
// Add characters starting from A which has ASCII value 65
int charLimit = 65 + numberOfTrees;
for(int i = 65; i < charLimit; i++) {
// Make new node.
Node newNode = new Node((char) i);
// Add that node to Tree as a root.
Tree newTree = new Tree();
newTree.setRoot(newNode);
// And add that one-node tree to forest(array)
forest.add(newTree);
}
Tree mainTree = forest.createMainTree();
mainTree.displayTree();
}
}
if(localRoot != null && i == nodeTree.length -1)
if you do not subtract one from node tree length you will have a duplicate child under the final parent node with 2 children
Anyone knows a good Java library I can use to parse a Newick file easily? Or if you have some tested source code I could use?
I want to read the newick file: http://en.wikipedia.org/wiki/Newick_format in java and generate a visual representation of the same. I have seen some java programs that do that but not easy to find how the parsing works in code.
Check out jebl (Java Evolutionary Biology Library) of FigTree and BEAST fame. Probably a lot more tree functionality than you might need, but it's a solid library.
Stumbled on this question while looking for a Java Newick parser.
I've also come across libnewicktree, which appears to be an updated version of the Newick parser from Juxtaposer.
I like to use the Archaeopteryx library based on the forester libraries. It can do a lot more than parsing and visualizing trees but its usage remains very simple even for basic tasks:
import java.io.IOException;
import org.forester.archaeopteryx.Archaeopteryx;
import org.forester.phylogeny.Phylogeny;
public class PhylogenyTree {
public static void main(String[] args) throws IOException{
String nhx = "(mammal,(turtle,rayfinfish,(frog,salamander)))";
Phylogeny ph = Phylogeny.createInstanceFromNhxString(nhx);
Archaeopteryx.createApplication(ph);
}
}
Here is a Newick parser I wrote for personal use. Use it in good health; there is no visualization included.
import java.util.ArrayList;
/**
* Created on 12/18/16
*
* #author #author Adam Knapp
* #version 0.1
*/
public class NewickTree {
private static int node_uuid = 0;
ArrayList<Node> nodeList = new ArrayList<>();
private Node root;
static NewickTree readNewickFormat(String newick) {
return new NewickTree().innerReadNewickFormat(newick);
}
private static String[] split(String s) {
ArrayList<Integer> splitIndices = new ArrayList<>();
int rightParenCount = 0;
int leftParenCount = 0;
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case '(':
leftParenCount++;
break;
case ')':
rightParenCount++;
break;
case ',':
if (leftParenCount == rightParenCount) splitIndices.add(i);
break;
}
}
int numSplits = splitIndices.size() + 1;
String[] splits = new String[numSplits];
if (numSplits == 1) {
splits[0] = s;
} else {
splits[0] = s.substring(0, splitIndices.get(0));
for (int i = 1; i < splitIndices.size(); i++) {
splits[i] = s.substring(splitIndices.get(i - 1) + 1, splitIndices.get(i));
}
splits[numSplits - 1] = s.substring(splitIndices.get(splitIndices.size() - 1) + 1);
}
return splits;
}
private NewickTree innerReadNewickFormat(String newick) {
// single branch = subtree (?)
this.root = readSubtree(newick.substring(0, newick.length() - 1));
return this;
}
private Node readSubtree(String s) {
int leftParen = s.indexOf('(');
int rightParen = s.lastIndexOf(')');
if (leftParen != -1 && rightParen != -1) {
String name = s.substring(rightParen + 1);
String[] childrenString = split(s.substring(leftParen + 1, rightParen));
Node node = new Node(name);
node.children = new ArrayList<>();
for (String sub : childrenString) {
Node child = readSubtree(sub);
node.children.add(child);
child.parent = node;
}
nodeList.add(node);
return node;
} else if (leftParen == rightParen) {
Node node = new Node(s);
nodeList.add(node);
return node;
} else throw new RuntimeException("unbalanced ()'s");
}
static class Node {
final String name;
final int weight;
boolean realName = false;
ArrayList<Node> children;
Node parent;
/**
* #param name name in "actualName:weight" format, weight defaults to zero if colon absent
*/
Node(String name) {
int colonIndex = name.indexOf(':');
String actualNameText;
if (colonIndex == -1) {
actualNameText = name;
weight = 0;
} else {
actualNameText = name.substring(0, colonIndex);
weight = Integer.parseInt(name.substring(colonIndex + 1, name.length()));
}
if (actualNameText.equals("")) {
this.realName = false;
this.name = Integer.toString(node_uuid);
node_uuid++;
} else {
this.realName = true;
this.name = actualNameText;
}
}
#Override
public int hashCode() {
return name.hashCode();
}
#Override
public boolean equals(Object o) {
if (!(o instanceof Node)) return false;
Node other = (Node) o;
return this.name.equals(other.name);
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (children != null && children.size() > 0) {
sb.append("(");
for (int i = 0; i < children.size() - 1; i++) {
sb.append(children.get(i).toString());
sb.append(",");
}
sb.append(children.get(children.size() - 1).toString());
sb.append(")");
}
if (name != null) sb.append(this.getName());
return sb.toString();
}
String getName() {
if (realName)
return name;
else
return "";
}
}
#Override
public String toString() {
return root.toString() + ";";
}
}
Seems like Tree Juxtaposer includes a newick tree parser (however limited to only one tree per file).