Okay so this is my first time using really any Design Pattern so forgive me but I'm really struggling with the concept. From what I've read there needs to be the Command interface, usually this would hold public void execute(); In my case I think I want to only have public void undo(); My question is on all the other classes that are required. My program is essentially done and I'm trying to merge this design pattern in at the end to put in a Undo function. It's a LinkedList that i defined with my own methods. Here's some of the code:
public class LinkedList<E> implements Serializable{
/** number of Nodes on the list */
private int count;
/** the first Node in the list */
private Node head;
/** the last Node in the list */
private Node tail;
/**Stack holding commands*/
private Stack<Command> undo = new Stack<Command>();
/** Inserts a given student's data into the database
* #param student given student data to be inserted into database
* #return none*/
public void insert(Student student){
//case where input is null
if(student.getName() == null || student.getGNumber() == null)
throw new IllegalArgumentException();
Node temp = head;
//case where there is no list
if(head == null){
head = new Node(student, null);
tail = head;
count = 1;
}
//case where top has existing Nodes
else{
//brings reference to end of list
while(temp.getNext() != null)
temp = temp.getNext();
temp.setNext(new Node(student, null));
tail = temp;
count ++;
}
}
Now would that be the receiver class? And do I still need a separate class for each command? Really all I want is an Undo Stack of commands, and each time I call a method I push it's undo onto that stack. For all the Command Design Pattern examples I could find they've all been the same example of that Light Switch which really doesn't do a good job showing a generic need.
Okay sorry for being really long winded, I guess here is the TL;DR question:
Can I add a Stack in my LinkedList, and then add a undo method also in the LinkedList that pops the stack? and add a push statement in each of my methods? or do I still need to go through all the steps and classes of the Command Design Pattern?
EDIT:
After some thought I realized to push a command into my Stack I need command objects for each of my methods, is there a way to implement this into my LinkedList class?
Related
I have been trying to create (I have been learning it) a doubly linked list based on an exercise, in which the list will be train with wagons. The exercise asks to create a class "wagon" with the attributes "name of wagon", "next wagon" and "previous wagon", and another class "train" with the methods to add wagons, print the wagons and sawp the order of the locomotives of the trains. My problem is in how the exercise asks to create the method to add wagons, and the one to swap the order of the locomotives. The method to add wagons has a parameter that has as data type the class "wagon", and I have really not gotten to create this method. I am going to show you what I have already done in the code below. Could anyone help me with that? I have not understood how to use the parameter "vagaoCriar" in the method.
Besides that, the exercise asks to create two trains (then two lists), and to change the two locomotives of the two trains. I would like to know if that is really possible with two doubly linked lists, to swap two elements of them between themselves, or could it be simply swapping the order of the two doubly linked lists, without having to change elements between them? Because I have already searched it enough and I have not found anything saying that it is possible to swap elements between two doubly linked lists. Still, I have had some problem to create the method to swap the locomotives of the train, because the method has as data type "wagon", but it has as parameter "name of wagon" (String), and the name of the method is "get wagon and remove", so I do not have idea what the exercise really wishes.
I understand that the questions is long, but for such a complex example (for me), I could not be concise.
public class Vagao {
String nomeDoVagao;
Wagon vagaoAnterior;
Wagon vagaoPosterior;
public Vagao (String nomeDoVagao){
this.nomeDoVagao = nomeDoVagao;
vagaoAnterior = null;
vagaoPosterior = null;
}
}
public class Trem {
Vagao head, tail = null;
//I do not know to proceed here
public void adicionarVagao (Vagao vagaoCriar){
Vagao novo_Vagao = new Vagao (vagaoCriar.nomeDoVagão);
if (head == null){
head = tail = novo_Vagao;
head.vagaoAnterior = null;
tail.vagaoPosterior = null;
} else {
tail.vagaoPosterior = novo_Vagao;
novo_Vagao.vagaoAnterior = tail;
tail = novo_Vagao;
tail.vagaoPosterior = null;
}
}
//This is the other method, that I have not understood well, so I have not
even begun it
public Vagao pegarVagaoRemover (String nomeDoVagao){...}
}
This is how I have tried to create a "train" and print it in the console, but it has not worked:
public class Main {
public static void main(String[] args) {
Trem trem = new Trem();
trem.adicionarVagao("qualquer");
trem.printTrem();
}
}
head and tail are not indepedant wagons themselves.
So one should not alter head's or tail's fields in general.
Adding at the end:
novo_Vagao.vagaoAnterior = null;
novo_Vagao.vagaoPosterior = null;
if (head == null){
head = tail = novo_Vagao;
} else {
novo_Vagao.vagaoAnterior = tail;
tail.vagaoPosterior = novo_Vago;
tail = novo_Vagao;
}
Removal would go:
if (vagao.vagaoPosterio == null) {
tail = vagao.vagaoAnterior;
} else {
vagao.vagaoPosterio.vagaoAnterio = vagao.vagaoAnterior;
}
...
So: what referencing fields to change.
Here is the code for the implementation of the Binary Search Tree:
public class BST<T extends Comparable<T>> {
BSTNode<T> root;
public T search(T target)
{
//loop to go through nodes and determine which routes to make
BSTNode<T> tmp = root;
while(tmp != null)
{
//c can have 3 values
//0 = target found
//(negative) = go left, target is smaller
//(positive) = go left, target is greater than current position
int c = target.compareTo(tmp.data);
if(c==0)
{
return tmp.data;
}
else if(c<0)
{
tmp = tmp.left;
}
else
{
tmp = tmp.right;
}
}
return null;
}
/*
* Need a helper method
*/
public T recSearch(T target)
{
return recSearch(target, root);
}
//helper method for recSearch()
private T recSearch(T target, BSTNode<T> root)
{
//Base case
if(root == null)
return null;
int c = target.compareTo(root.data);
if(c == 0)
return root.data;
else if(c<0)
return recSearch(target, root.left);
else
return recSearch(target, root.right);
}
Why do I need the recursive helper method? Why can't I I just use "this.root" to carry out the recursive process that is taking place? Furthermore, if screwing up the root property of the object this method is being called on is a problem, then how is does the helper method prevent this from happening? Does it just create a pointer that is separate from the this.root property, and therefore won't mess up the root property of the object that the method is being called on?
Sorry if the question doesn't seem straight forward, but if anyone can enlighten me on what's exactly going on behind the scenes I would really appreciate it.
The method needs a starting point. It needs to have a non changing Target node and it needs to compare it with some other node to see if they are a match lets call this node current instead of root since it is the current Node the recursive method is evaluating. There really isn't a concise way of doing this when using a recursive method other than using a helper function and passing in both variables (this is the case for many recursive methods). As you said stated if you updated root you would completely alter your tree when going left or right which you wouldn't want to do. The helper function is used because it gives your recursive method a starting point. And it also keeps track of the current node you are working on as you said the method points to the Node object being evaluated but doesn't make any changes. When going left or right it doesn't modify anything it just passes in a reference to the left or right node and continues to do this until the target is found or the base case is hit.
I have this linked list method that is used to insert before, so it takes a node and puts it before the beforeNode. Currently it does that, but then it goes on forever and makes the linked list infinitely big when it should only be four long. Does anyone see why it keeps on going?
private void insertBefore(Node aNode, Node beforeNode)
{
if(this.getPrevious(beforeNode) != null) {
this.getPrevious(beforeNode).setNext(aNode);
// aNode.setPrevious(beforeNode);
//this.getPrevious(this.getPrevious(beforeNode)).setNext(aNode);
} else {
head = aNode;
}
aNode.setNext(beforeNode);
// beforeNode.setPrevious(aNode);
}
Here is the print list method that could have something to do with it, but I dont think so
public void printList()
{
Node currentNode;
currentNode = this.getHead();
System.out.print("head ->");
while(currentNode!=null)
{
System.out.print(currentNode.getData().toString()+ " -> ");
currentNode = currentNode.getNext();
}
System.out.println("|||");
}
I think some how you are passing the same node for both aNode and beforeNode. In java, every object is a reference. Did you by any chance try to create aNode a copy of beforeNode ? It might have made both the same and causing the linked list to have a self loop. use a copy constructor or things like clone to get a duplicate node.
Is there a way to recursively traverse a tree and return an array that is scoped to that recursive method?
So I recently answered someone else's question on this topic. That question can be found here: SO Question. My solution uses an array outside of the scope of the recursion, and therefore the method cannot (or at least probably should not) return the array. However, is there a way to write a recursive method for traversing trees such that it returns an array? Even writing an initial method that calls the recursive one would be fine, but I can't think of a good way to do this.
Here's the code that I suggested before:
private List nodeValues = new ArrayList();
public void traversePreRecursive(BinarySearchTreeNode node)
{
if (node != null)
{
nodeValues.add(node.getValue());
traversePreRecursive(node.getLeft());
traversePreRecursive(node.getRight());
}
}
As you can see the ArrayList is outside of the scope of the recursion - And therefore returning it doesn't make a lot of sense. Is there a better way to do this?
public static List traversePreRecursive(Node node) {
if (node == null) return new ArrayList();
List nodeValues = new ArrayList();
nodeValues.add(node.getValue());
nodeValues.addAll(traversePreRecursive(node.getLeft()));
nodeValues.addAll(traversePreRecursive(node.getRight()));
return nodeValues;
}
There is an alternative, but it involves two passes over the tree. You would only employ this alternative if the array operations in my first answer were giving you grief. This approach starts by providing an index for each of the nodes (the index() method) -- basically working out which element of the array a node should occupy before we actually create the array. This also gives me a count of nodes (size). I then allocate an array (list) big enough to hold all the nodes and pass it into a method (addToList) that copies the node-references into the previously identified element in the array.
public static List<Node> getNodes(Node a) {
int size = index(a, 0);
List<Node> list = new ArrayList<Node>(size);
addToList(a, list);
return list;
}
private static int index(Node node, int index) {
if (node == null) return index;
node.setIndex(index);
int iLeft = index(node.getLeft(), index++);
int iRight = index(node.getRight(), iLeft++);
return iRight + 1;
}
private static void addToList(Node node, List<Node> list) {
if(node == null) return;
list.add(node.getIndex(), node);
addToList(node.getLeft(), list);
addToList(node.getRight(), list);
}
In c you can have static function variables,(Ie, adding a value to a list in one iteration of a function means that that value will be in the list in the next iteration--if the list is static) but using them isn't the best (most optimal) solution for the problem you are suggesting. So, I think you are searching for static variables, but this isn't an appropriate case to use them.
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.