Creating a linked list of notes from a Phrase (Jmusic) - java

I have this constructor that takes in a phrase of jmusic notes, and I'm trying to set each individual note to an individual node in a linked list of SoloNodes which hold one individual note only. most of the methods in that constructor I've written myself but they're pretty self explanatory. What exactly must I do to make this generate a linked list?
public Solo(Phrase myPhrase)
{
int length=myPhrase.length();
head=new SoloNode();
SoloNode next=new SoloNode();
for(int i=1; i<=length;i++)
{
head.setNote(myPhrase.getNote(i));
next=head.copyNode();
head.setNext(next);
head=next;
i++;
}
}

I guess that's the code you are looking for:
private SoloNode head;
public Solo(Phrase myPhrase)
{
int length = myPhrase.length();
SoloNode node = new SoloNode();
head = node;
for (int i = 0; i < length; i++) {
node.setNote(myPhrase.getNote(i));
if (i + 1 < length) {
node.setNext(new SoloNode());
node = node.getNext();
}
}
}
I assumed you are using a class SoloNode which looks like this.
I assumed too that myPhrase.getNote(i) starts with index 0 (not 1) because that is the common way how it works in Java.
After you run this code the SoloNodes are filled with data from myPhrase and linked from one to next. With getNext() you can navigate from current to next. Only for last SoloNode it will return null.

Related

Is there a way I can combine these two methods?

Currently I'm creating a method to reverse a linkedlist in java, but it requires two methods:
public void reverse(){
reverse(head);
}
private void reverse(Node h){
if(h.next==null){
System.out.print(h.data+" ");
return;
}
reverse(h.next);
System.out.print(h.data+" ");
}
This way I call the reverse method with 0 parameters, which then calls the other reverse method. Is there any way to make them 1 method without changing the other aspects of my LinkedList class?
Thanks in advance!
It is very common to have a public method calling a private recursive method with extra parameter(s). See the source code for Arrays.deepToString(Object[]) for an example of this.
However, in your case it may be better to avoid recursion completely. One problem with recursion is that you are only able to nest method calls to a certain depth before you get a StackOverflowError.
An alternative is to use loops instead. The following would work:
public void reverse(){
List<Node> nodes = new ArrayList<>();
for (Node n = head; n != null; n = n.next)
nodes.add(n);
for (int i = nodes.size() - 1; i >= 0; i--)
System.out.print(nodes.get(i).data + " ");
}
Technically, there is a way, but I would not recommend it. This is it:
public void reverse( Node... nodes )
{
Node h;
if( nodes.length == 0 )
h = head;
else
{
assert nodes.length == 1;
h = nodes[0];
}
if( h.next == null )
{
System.out.print( h.data + " " );
return;
}
reverse( h.next );
System.out.print( h.data + " " );
}
Note that this would also require making class Node public, which is also not a good idea. (Or you might just get a warning for having a public method accepting a parameter of a private type, which you can then suppress; I don't remember.)
But Paul Boddington's comment is right on the money.
Paul beat me to a similar answer, but I figured I'd post mine anyways since I assumed that you do not want to use ArrayList as a dependency:
Yes it is possible. If it is a doubly linked list you could traverse the list to the last node then walk the list to the front. However, I will also assume it's a single linked list, so I'll answer using an array to store all node references. Also, I assume you have another method to calculate length.
public void reverse() {
int length = length();
Node [] nodes = new Node[length];
Node currentNode = head;
int i = 0;
// Populate the array
while(currentNode != null)
{
nodes[i] = currentNode;
currentNode = currentNode.next;
i++;
}
// Iterate backwards to print the array
for(int j = length -1; j >= 0; j--)
{
System.out.println(nodes[i] + " ");
}
}
Yes. You can make the parameter in your displayed second method "act" as an Optional Parameter. In the method declaration below we're in essence making the Node Type parameter to be an Node array which can be passed as empty. Since we're only need to pass 1 parameter to our method then we only need the supplied Node data contained in the element Index of 0 (the first element of the array).
Within the method itself we declare a Node variable which was the same type and name as what your parameter was so to eliminate any confusion within the code body of the method and we provide a default of 0 (default can be whatever you want). We then check the new headerInfo[] array parameter to see if there was anything supplied and if there was then we apply that data from the first element of the headerInfo[] array (since we're only using one parameter for this method) to the new Node type variable h. The args[] parameter for the main method in a class does the same thing.
public void reverse(Node... headerInfo){
Node h = 0;
if (headerinfo.length != 0) { h = headerInfo[0]; }
if(h.next==null){
System.out.print(h.data+" ");
return;
}
reverse(h.next);
System.out.print(h.data+" ");
}
Now the method can be can be called as reverse() or reverse(head)
EDIT:
Whops...Mike beat me to it :)

Develop a 2-3 search tree in java

I have been given an assignment to create a 2-3 search tree that is supposed to support a few different operations each divided in to different stages of the assignment.
For stage 1 I'm supposed to suport the operations get, put and size. I'm curently trying to implement the get operation but I'm stuck and I can't wrap my head around how to continue so I'm questioning all of my code I have written and felt like a need someone elses input.
I have looked around how to develop a 2-3 search tree but what I found was alot of code that made no sence to me or it just did not do what I needed it to do, and I wanted to try and make it for my self from scratch and here we are now.
My Node class
package kth.id2010.lab.lab04;
public class Node {
boolean isLeaf = false;
int numberOfKeys;
String[] keys = new String[2]; //each node can contain up to 2 keys
int[] values = new int[2]; //every key contains 2 values
Node[] subtrees = new Node[3]; //every node can contain pointers to 3 different nodes
Node(Node n) {
n.numberOfKeys = 0;
n.isLeaf = true;
}
}
My Tree creating class
package kth.id2010.lab.lab04;
public class Tree {
Node root; // root node of the tree
int n; // number of elements in the tree
private Tree(){
root = new Node(root);
n = 0;
}
//Return the values of the key if we find it
public int[] get(String key){
//if the root has no subtrees check if it contain the right key
if(this.root.subtrees.length == 0){
if(this.root.keys[0] == key){
return(this.root.keys[0].values);
}
else if(this.root.keys[1] == key){
return(this.root.keys[1].values);
}
}
//if noot in root, check its subtree nodes
//and here I can't get my head around how to traverse down the tree
else{
for(int i = 0; i < this.root.subtrees.length; i++){
for(int j = 0; j < this.root.subtrees[i].keys.length; j++){
if(this.root.subtrees[i].keys[j] == key){
return(this.root.subtrees[i].keys[j].values);
}
}
}
}
return null;
}
}
What I can tell for my self is that I need to find a way to bind values[] to each key but I can't figure out a way how. Might be the lack of sleep or that I'm stuck in this way of thinking.
bind values[] to each key
It might make more sense to use a HashMap to do that mapping for you, since that's what it's for. Beyond that, if you have two keys and each key has two values, you have 4 values, not 2 ;)
In general, the get method in a tree structure is almost always implementable recursively. Here is a very general implementation of a get algorithm for a 2-3 tree in psudo-code.
V get<K, V>(Node<K, V> node, K key)
{
if(node.is_leaf())
{
return node.keys.get(key); // This will either return the value, or null if the key isn't in the leaf and thus not in the tree
}
if(key < node.left_key)
{
return get(node.left_child, key); // If our key goes to the left, go left recursively
}
else if(node.two_node && key <= node.right_key)
{
return get(node.center_child, key) // If we have two keys, and we're less than the second one, we go down the center recursively
}
else
{
return get(node.right_child, key); // If we've gotten here, we know we're going right, go down that path recursively
}
}
That should get you started in the right direction. Insertion/deletion for 2-3 trees is a bit more complicated, but this should at least get your head around how to think about it. Hint; Your Node class needs to be doubly-linked, that is each node/leaf needs to reference its parent node as well as its children, and the root is simply a node whose parent is null.

Iterators over Tries in Java

I am currently trying to implement a trie data structure for integer tuples. And have implemented as follows:
import java.util.ArrayList;
public class TrieNode {
int num;
ArrayList<TrieNode> links;
boolean endOfTuple;
public TrieNode(int num)
{
this.num = num;
links = new ArrayList<TrieNode>();
this.endOfTuple = false;
}
}
I then have a trie class as follows:
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode(-1);
}
public void insertTuple(int[] tuple)
{
int l = tuple.length;
TrieNode curNode = root;
for (int i = 0; i < l; i++)
{
TrieNode node = new TrieNode(tuple[i]);
if(!curNode.links.contains(node)){
curNode.links.add(node);
}
curNode = curNode.links.get(curNode.links.indexOf(node));
}
curNode.endOfTuple = true;
}
}
I can add values to this trie, but i need to be able to iterate over this and was wondering how i could do this? For example if i wanted to print the tree using an iterator...Any help will be great...
All you need for an interator is to implement the Iterator interface, which only requires that you supply boolean hasNext() and Integer next(). So the question to ask is: how do represent a position in your trie, such that it's possible to (a) fetch the value associated with that position, and (b) figure out the "next" position given a current one?
I'll refrain from posting an actual solution since I'm not sure whether this is homework. But consider: you can represent a "current position" in your trie just by choosing a particular trie node, and the path of trie nodes you used to reach it. Then you can compute the "next" element recursively: if the current element is a node that has children, then find the first child for which endOfTuple is true. If the current element doesn't have children, then go to its parent and advance to that parent's next child. If that parent doesn't have next children, then go it its parent's next child, etc.

Building a linked list in Java

This is an example from my book. As I see it, when you create a list with this class, you create two objects (first and last, which are null). I can't figure out why, when you put both first and last "Node" objects in the add method. Shouldn't it create two elements when you set both first = n and last = n. For example, if I call list.add(2), shouldn't both first and last be 2 now ?
public class List {
private Node first = null;
private Node last = null;
public List(){
first = null;
last = null;
}
private static class Node{
public int value;
public Node next;
public Node ( int value, Node next){
this.value = value;
this.next = next;
}
}
public void add (int value){
Node n = new Node (value,null);
if(first==null){
first = n;
last = n;
}else{
last.next = n;
last = n;
}
}
public int size(){
int number = 0;
Node n = first;
while(n != null){
number++;
n = n.next;
}
return number;
}
}
As i see it, when u create a list with this class, you create two objects (first and last, which are null).
That's not true. first and last are not objects, but references to objects. And in this case, they start out as null references, meaning that they don't refer to any object at all.
When you write first = n; last = n;, you set first and last to both refer to the same object — whatever object n refers to.
For example, if list.add(2), shouldn't now both first and last be 2?
Yes, they'll both refer to the same Node instance, whose value is 2.
Yes i see that first and last are needed. Probably later on first will be much more useful if you have dequeue (remove first) or a search (which i guess can be done from the end rather than at the start, same process for a simple linear search).
As for your question. Yes if you started with a blank list and said list.add(2). Both first and last will be pointing to node with value 2. This is because the first element and the last element in the list are the same, hence 1 element in the list. Its both first and last (and middle if you want to be weird).
but if you did list.add(1), list.add(2). You would get first = node.value == 1 and second = node.value == 2

Manual Linked List - Insert before method

This is part of an exercise we did in class, I just can't figure it out...
The required method is the insertBefore(object data) method wherein when a user choose this method it will prompt it to enter a data to be inserted before the reference data(input by user)
An example of how it should run:
// assuming linked list has data 1,2,3 inserted already
Choose Method:
1)Insert Before
choice: 1 // input by user
====Insert Before====
Enter Reference data: 2 // input by user
Enter Data to be inserted: 5 // input by user
supposed output: 1,5,2,3
Here's my code for this exercise: (This is inside a class called LinkList with variables
protected int end;
protected Node start;
and an inner class called Node)
private class Node
{
public char data;
public Node next;
public Node(char data)
{
this.data = data;
}
}
public void insertBef(char ref,char data)
{
Node temp = new Node(data);
Node current = start;
if(end!=0)
{
for(int i = 1; i<end; i++)
{
if(current == start)
{
Node newNode = start;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
else if(current.data == ref)
{
Node newNode = current;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
}
end++;
}
else
{
temp.next = start;
start = temp;
}
end++;
}
But when I run my code it ouputs 3,5, not 1,5,2,3! I can't see where I might have gone wrong...
Can someone please tell me where the mistake is, and explain how I might fix it?
I understand that to be able to insert before a reference value you should:
Make a new node for the new data
Make a temporary node for the reference value and link
Make the link of the data before the reference value point to the new node and make the link of the new node point to the temporary node
I just can't seem to figure out how to implement it in Java code...
When programming, if it seems hard, you're probably going about it the wrong way...
You only need one line of code to accomplish the task!
list.add(list.indexOf(reference), data);
Here's this line wrapped as an insertBefore method:
public static void insertBefore(List<Integer> list, int reference, int data) {
list.add(list.indexOf(reference), data);
}
Here's a test using your example:
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
insertBefore(list, 2, 5);
System.out.println(list);
}
Output:
[1, 5, 2, 3]
Note: This code will throw an exception if the reference element is not found.
I'll leave it to you to plug that hole.
First things first: for loops are generally a bad idea with linked lists. while loops are much better; you can do something like while(next != null).
Looking at your code, you seem to have a few problems.
Your for loop is overly complicated, and doesn't seem to make a lot of sense. Here's how your loop should look:
Get head node
Begin looping through the list, checking the next node's value as you go
Once you find that the next node's value is the one you're looking for, creating a new node.
Insert the new node by setting its Next value to be equal to the current node's Next value, then set the current node's next value to be the new node.
Return from the function.
Your middle bullet point is actually unnecessary, and I have no idea what you use end for. Regardless, you seem to have the basic principle down, so I won't feel like I'm spoiling you by posting code.
Now, I'm not sure what your start is. Does it hold a value, or is it a dedicated head node? I'd vote for a dedicated head node, I generally find it easier to work with because you don't need to add code for a special case where the number should come before the head. So your start node should be "empty"; the value it holds is ignored, the only thing it's used for is to keep a pointer to the first legit node in the list. If you do this, the insertBef method becomes incredibly simple. NOTE: untested code to follow.
public void insertBef(char ref, char data)
{
Node current = start;
while( current.next != null )
{
if( current.next.value == ref )
{
Node n = new Node(data);
n.next = current.next;
current.next = n;
return;
}
current = current.next;
}
}
Please don't just copy the code. If you have questions, post them and I'll do my best to answer.

Categories

Resources