first commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+305
@@ -0,0 +1,305 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while () {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>();
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+491
@@ -0,0 +1,491 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
Integer number = 0;
|
||||
numberLeaf(root, number);
|
||||
return number;
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : numberLeaf(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : numberLeaf(node.getRight());
|
||||
|
||||
int i;
|
||||
if ()
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
}
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
|
||||
|
||||
// METODI
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+468
@@ -0,0 +1,468 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package jcf_set.example;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
new InteriRipetuti().run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET
|
||||
Set<Integer> hashset = new HashSet<Integer>();
|
||||
|
||||
// Genero i numeri casuali inserendoli in nel set di hashset
|
||||
Random generator = new Random();
|
||||
for (int i = 0; i < N; i++) {
|
||||
Integer x = generator.nextInt(MAX_INT + 1);
|
||||
if (!hashset.add(x)) {
|
||||
System.out.println("[NON INSERITO] Causa: Intero ripetuto: " + x);
|
||||
} else System.out.println("Intero inserito: " + x);
|
||||
}
|
||||
|
||||
// Stampa di hashset
|
||||
System.out.println("Hashset");
|
||||
for (Integer x : hashset) System.out.println(x + " ");
|
||||
System.out.println(); System.out.println(hashset);
|
||||
}
|
||||
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData != null)
|
||||
}
|
||||
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package vettore_ordinabile;
|
||||
|
||||
public class VettoriIntero {
|
||||
|
||||
}
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if ()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+439
@@ -0,0 +1,439 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
BinaryNode<E> currentNode = root;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
E currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
currentNode.setData(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package stack;
|
||||
|
||||
public interface MyStack<T> {
|
||||
|
||||
/**
|
||||
* Aggiunge un elemento al top dello stack.
|
||||
* @param Elemento che deve essere aggiunto nello stack.
|
||||
*/
|
||||
void push(T item);
|
||||
|
||||
/**
|
||||
* Rimuove l'elemento al top dello stack.
|
||||
* @return Elemento appena rimosso dallo stack;
|
||||
*/
|
||||
T pop();
|
||||
|
||||
T peek();
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package stack;
|
||||
|
||||
public class StackExample {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
MyStack<Character> stack = new ArrayListStack<Character>();
|
||||
|
||||
Character a = 'a';
|
||||
Character b = 'b';
|
||||
Character c = 'c';
|
||||
Character d = 'd';
|
||||
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
stack.push(c);
|
||||
stack.push(d);
|
||||
|
||||
// Svuotiamo lo stack
|
||||
for (int i = stack.size(); i < stack.size(); i++) {
|
||||
Character current = stack.pop();
|
||||
System.out.println(current);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+492
@@ -0,0 +1,492 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
Integer number = 0;
|
||||
numberLeaf(root, number);
|
||||
return number;
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : numberLeaf(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : numberLeaf(node.getRight());
|
||||
|
||||
int i;
|
||||
|
||||
if ()
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package parziale.p251110;
|
||||
|
||||
public class Paziente {
|
||||
|
||||
private String id;
|
||||
private int annoNascita;
|
||||
|
||||
public Paziente(
|
||||
String id,
|
||||
int annoNascita) {
|
||||
this.id = id;
|
||||
this.annoNascita = annoNascita;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getAnnoNascita() {
|
||||
return annoNascita;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Paziente))
|
||||
}
|
||||
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsRightChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldRight = this.parent.right;
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
public class Videogioco implements Comparable<Videogioco>{
|
||||
|
||||
// Campi di istanza
|
||||
private String titolo;
|
||||
private String piattaforma;
|
||||
private Integer annoUscita;
|
||||
private Double prezzo;
|
||||
private Integer voto;
|
||||
|
||||
// Costruttore
|
||||
|
||||
private Videogioco() {}
|
||||
|
||||
public Videogioco(
|
||||
String titolo,
|
||||
String piattaforma,
|
||||
Integer annoUscita,
|
||||
Double prezzo,
|
||||
Integer voto) {
|
||||
this.titolo = (titolo == null) ? "" : titolo.trim();
|
||||
this.piattaforma = (piattaforma == null) ? "" : piattaforma.trim();
|
||||
this.annoUscita = (annoUscita == null) ? 0 : annoUscita;
|
||||
this.prezzo = (prezzo == null) ? 0.0 : prezzo;
|
||||
this.voto = (voto == null) ? 0 : voto;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree.root = root.getLeft();
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package binary_tree;
|
||||
|
||||
public class ExerciseBinaryTree {
|
||||
|
||||
|
||||
/*
|
||||
* Esercizio 1 II parziale 10.01.2018
|
||||
* Un albero binario di interi si dice pari se tutti i nodi contengono
|
||||
* un intero positivo pari. Realizzare il metodo statico
|
||||
* public static boolean IsEvenBtree (BinaryTree<Integer> btree)
|
||||
* che verifica se l'albero binario dato btree e' pari.
|
||||
*/
|
||||
public static boolean isEvenBtree(BinaryTree<Integer> btree) {
|
||||
boolean even = true;
|
||||
}
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
}
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public void numberLeaf() {
|
||||
Integer number = 0;
|
||||
numberLeaf(root, number);
|
||||
}
|
||||
|
||||
public void numberLeaf(BinaryNode<E> node, Integer number) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) number++;
|
||||
else {
|
||||
numberLeaf(node.getLeft(), number);
|
||||
numberLeaf(node.getRight(), number);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
ArrayList<Videogioco> giochi = new ArrayList<Videogioco>();
|
||||
|
||||
giochi.add(new Videogioco("The Last of Us Part II", "PS5", 2020, 39.99, 9));
|
||||
giochi.add(new Videogioco("Cyberpunk 2077", "PC", 2020, 29.99, 8));
|
||||
giochi.add(new Videogioco("Minecraft", "PC", 2011, 19.99, 10));
|
||||
giochi.add(new Videogioco("Ghost of Tsushima", "PS5", 2020, 49.99, 9));
|
||||
giochi.add(new Videogioco("Resident Evil 4 Remake", "PS5", 2023, 44.99, 9));
|
||||
giochi.add(new Videogioco("GTA V", "PC", 2013, 14.99, 8));
|
||||
giochi.add(new Videogioco("God of War Ragnarok", "PS5", 2022, 59.99, 10));
|
||||
giochi.add(new Videogioco("Fortnite", "PC", 2017, 0.0, 7));
|
||||
|
||||
// Per adoperare il comparable
|
||||
Collections.sort(giochi);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private <T> void printList(List<T> lista) {
|
||||
System.out.print("{");
|
||||
for (int i = 0; i < lista.size(); i++) {
|
||||
System.out.print(" [");
|
||||
System.out.print(lista.get(i).toString());
|
||||
System.out.print("] ");
|
||||
}
|
||||
System.out.print("}");
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayListQueue<T> implements MyQueue<T> {
|
||||
|
||||
private List<T> queue = new ArrayList<T>();
|
||||
|
||||
@Override
|
||||
public boolean offer(T item) {
|
||||
return queue.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
return queue.removeFirst():
|
||||
}
|
||||
|
||||
}
|
||||
+483
@@ -0,0 +1,483 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
Integer number = 0;
|
||||
numberLeaf(root, number);
|
||||
return number;
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (this.parent == null) return null;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package stack;
|
||||
|
||||
public interface MyStack<T> {
|
||||
|
||||
void push(T item);
|
||||
|
||||
T pop();
|
||||
|
||||
T peek();
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
stackOfNodes.push(current);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder();
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package parziale.p251110;
|
||||
|
||||
public class Paziente implements Comparable<Paziente> {
|
||||
|
||||
private String id;
|
||||
private int annoNascita;
|
||||
|
||||
public Paziente(
|
||||
String id,
|
||||
int annoNascita) {
|
||||
this.id = id;
|
||||
this.annoNascita = annoNascita;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getAnnoNascita() {
|
||||
return annoNascita;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Paziente)) return false;
|
||||
|
||||
Paziente p = (Paziente) o;
|
||||
|
||||
return id.equals(p.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Paziente p) {
|
||||
if (annoNascita < p.annoNascita) return -1;
|
||||
if (annoNascita > p.annoNascita) return 1;
|
||||
return id.compareTo(p.id);
|
||||
}
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
}
|
||||
+248
@@ -0,0 +1,248 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
protected void itpreorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package jcf_set.example;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET
|
||||
Set<Integer> hashset = new HashSet<Integer>();
|
||||
|
||||
// Genero i numeri casuali inserendoli in nel set di hashset
|
||||
Random generator = new Random();
|
||||
for (int i = 0; i < N; i++) {
|
||||
Integer x = generator.nextInt(MAX_INT + 1);
|
||||
if (!hashset.add(x)) {
|
||||
Syste
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main (String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsRightChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldRight = this.parent.right;
|
||||
this.parent.right = this;
|
||||
|
||||
return oldRight;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setAsRoot() {
|
||||
if (parent == null) return null;
|
||||
|
||||
BinaryNode<E> oldParent = parent;
|
||||
parent = null;
|
||||
|
||||
if (oldParent.left == this) oldParent.left = null;
|
||||
else oldParent.right = null;
|
||||
|
||||
return oldParent;
|
||||
}
|
||||
|
||||
public boolean hasLeft() {
|
||||
return left != null;
|
||||
}
|
||||
|
||||
public boolean hasRight() {
|
||||
return right != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) return false;
|
||||
if (other == this) return true;
|
||||
if (!(other instanceof BinaryNode<?>)) return false;
|
||||
|
||||
BinaryNode<?> otherType = (BinaryNode<?>)other;
|
||||
|
||||
return this.left.equals(otherType.left)
|
||||
&& this.right.equals(otherType.right)
|
||||
&& this.parent.equals(otherType.parent)
|
||||
&& this.data.equals(otherType.data);
|
||||
}
|
||||
|
||||
}
|
||||
+281
@@ -0,0 +1,281 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
}
|
||||
|
||||
// ITERATOR
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package parziale.p251110;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class Clinica {
|
||||
|
||||
ArrayList<Paziente> pazienti = new ArrayList<Paziente>();
|
||||
|
||||
// 1. Numero di pazienti Ricoverati
|
||||
public int pazientiRicoverati() {
|
||||
return pazienti.size();
|
||||
}
|
||||
|
||||
// 2. Inserimento del paziente
|
||||
/*
|
||||
* Dal momento che non ci è permesso adoperare
|
||||
* TreeSet per l'ordine e per l'unicità
|
||||
*/
|
||||
public boolean ricoveraPaziente(Paziente paziente) {
|
||||
// Se il paziente è nullo, nulla verrà aggiunto
|
||||
if (paziente == null) return false;
|
||||
|
||||
// Controllo se il paziente è già presente nella lista ricoveri
|
||||
Iterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
Paziente current = it.next();
|
||||
if (paziente.equals(current)) return false; // Se è già presente un paziente con id uguale allora non viene aggiunto e ritorna false
|
||||
}
|
||||
|
||||
// Aggiunta del paziente
|
||||
ListIterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
Paziente current = it.next();
|
||||
int cmp = current.compareTo(paziente);
|
||||
if (cmp > 1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null)
|
||||
}
|
||||
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
}
|
||||
+494
@@ -0,0 +1,494 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
return numberLeaf(root);
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
if (node.getLeft() == null && node.getRight() == null) return 1;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : numberLeaf(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : numberLeaf(node.getRight());
|
||||
|
||||
return nLeft + nRight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che trasforma l'albero corrente
|
||||
* in modo che ogni suo nodo interno abbia esattamente due figli. Se un nodo ha solo un
|
||||
* figlio, si aggiunga l'altro nodo figlio come copia del figlio esistente
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class TreeSetExample2 {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
TreeSet<String> tree1 = new TreeSet<String>();
|
||||
}
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package stack;
|
||||
|
||||
public class StackExample {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
MyStack<Character> stack = new ArrayListStack<Character>();
|
||||
|
||||
Character a = 'a';
|
||||
Character b = 'b';
|
||||
Character c = 'c';
|
||||
Character d = 'd';
|
||||
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
stack.push(c);
|
||||
stack.push(d);
|
||||
|
||||
// Svuotiamo lo stack
|
||||
for (int i = 0; i < stack.size(); i++) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsRightChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldRight = this.parent.right;
|
||||
this.parent.right = this;
|
||||
|
||||
return oldRight;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setAsRoot() {
|
||||
if (parent == null) return null;
|
||||
|
||||
BinaryNode<E> oldParent = parent;
|
||||
parent = null;
|
||||
|
||||
if (oldParent.left == this) oldParent.left = null;
|
||||
else oldParent.right = null;
|
||||
|
||||
return oldParent;
|
||||
}
|
||||
|
||||
public boolean hasLeft() {
|
||||
return left != null;
|
||||
}
|
||||
|
||||
public boolean hasRight() {
|
||||
return right != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) return false;
|
||||
if (other == this) return true;
|
||||
if (!(other instanceof BinaryNode<?>))
|
||||
}
|
||||
|
||||
}
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
}
|
||||
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
}
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ExerciseBinaryTree {
|
||||
|
||||
|
||||
/*
|
||||
* Esercizio 1 II parziale 10.01.2018
|
||||
* Un albero binario di interi si dice pari se tutti i nodi contengono
|
||||
* un intero positivo pari. Realizzare il metodo statico
|
||||
* public static boolean IsEvenBtree (BinaryTree<Integer> btree)
|
||||
* che verifica se l'albero binario dato btree e' pari.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione, in questo caso, non stiamo operando direttamente
|
||||
* dall'interno dell'albero, quindi possiamo sfruttare gli iteratori.
|
||||
* Essendo che dobbiamo per forza verificare tutit i vari nodi possiamo
|
||||
* adoperare qualsiasi tipo di iteratore.
|
||||
*/
|
||||
public static boolean isEvenBtree(BinaryTree<Integer> btree) {
|
||||
boolean even = true;
|
||||
Iterator<Integer> iterator = btree.iteratorInOrder();
|
||||
while (iterator.hasNext() && even) {
|
||||
Integer current = iterator.next();
|
||||
if ((current <= 0) || !(current % 2 == 0)) even = false;
|
||||
}
|
||||
return even;
|
||||
}
|
||||
|
||||
/*
|
||||
* Esercizio 2
|
||||
* Realizzare il metodo statico public static Integer MaxValue(BinaryTree<Integer> btree)
|
||||
* che restituisce il riferimento all'oggetto intero più grande
|
||||
* contenuto in btree.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione, in questo caso, è necessario e sufficiente iterare tutti gli elementi per
|
||||
* verificare il maggiore. Non essendoci un vero ordinamento sull'albero siamo obbligati a
|
||||
* iterare tutti i nodi.
|
||||
*/
|
||||
public static Integer maxValue(BinaryTree<Integer> btree) {
|
||||
Iterator<Integer> iterator = btree.iteratorInOrder();
|
||||
Integer maxValue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ExerciseBinaryTree {
|
||||
|
||||
|
||||
/*
|
||||
* Esercizio 1 II parziale 10.01.2018
|
||||
* Un albero binario di interi si dice pari se tutti i nodi contengono
|
||||
* un intero positivo pari. Realizzare il metodo statico
|
||||
* public static boolean IsEvenBtree (BinaryTree<Integer> btree)
|
||||
* che verifica se l'albero binario dato btree e' pari.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione, in questo caso, non stiamo operando direttamente
|
||||
* dall'interno dell'albero, quindi possiamo sfruttare gli iteratori.
|
||||
* Essendo che dobbiamo per forza verificare tutit i vari nodi possiamo
|
||||
* adoperare qualsiasi tipo di iteratore.
|
||||
*/
|
||||
public static boolean isEvenBtree(BinaryTree<Integer> btree) {
|
||||
boolean even = true;
|
||||
Iterator<Integer> iterator = btree.iteratorInOrder();
|
||||
while (iterator.hasNext() && even) {
|
||||
Integer current = iterator.next();
|
||||
if (!(current % 2 == 0)) even = false;
|
||||
}
|
||||
return even;
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package stack;
|
||||
|
||||
public class StackExample {
|
||||
|
||||
}
|
||||
+432
@@ -0,0 +1,432 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
BinaryNode<E> currentNode = root;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
E currentObject = iterator.next();
|
||||
|
||||
currentNode.setData(currentObject);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET
|
||||
}
|
||||
|
||||
}
|
||||
+224
@@ -0,0 +1,224 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) templist.add();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+383
@@ -0,0 +1,383 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
}
|
||||
|
||||
}
|
||||
+500
@@ -0,0 +1,500 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
return numberLeaf(root);
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
if (node.getLeft() == null && node.getRight() == null) return 1;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : numberLeaf(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : numberLeaf(node.getRight());
|
||||
|
||||
return nLeft + nRight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che trasforma l'albero corrente
|
||||
* in modo che ogni suo nodo interno abbia esattamente due figli. Se un nodo ha solo un
|
||||
* figlio, si aggiunga l'altro nodo figlio come copia del figlio esistente
|
||||
*/
|
||||
public void makeFull() {
|
||||
makeFull(root);
|
||||
}
|
||||
|
||||
public void makeFull(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
}
|
||||
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package test;
|
||||
|
||||
public class Main {
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package parziale.p251110;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class Clinica {
|
||||
|
||||
ArrayList<Paziente> pazienti = new ArrayList<Paziente>();
|
||||
|
||||
// 1. Numero di pazienti Ricoverati
|
||||
public int pazientiRicoverati() {
|
||||
return pazienti.size();
|
||||
}
|
||||
|
||||
// 2. Inserimento del paziente
|
||||
/*
|
||||
* Dal momento che non ci è permesso adoperare
|
||||
* TreeSet per l'ordine e per l'unicità
|
||||
*/
|
||||
public boolean ricoveraPaziente(Paziente paziente) {
|
||||
// Se il paziente è nullo, nulla verrà aggiunto
|
||||
if (paziente == null) return false;
|
||||
|
||||
// Controllo se il paziente è già presente nella lista ricoveri
|
||||
Iterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
Paziente current = it.next();
|
||||
if (paziente.equals(current)) return false; // Se è già presente un paziente con id uguale allora non viene aggiunto e ritorna false
|
||||
}
|
||||
|
||||
// Aggiunta del paziente
|
||||
Iterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+502
@@ -0,0 +1,502 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
E currentObject = iterator.next();
|
||||
root = new BinaryNode<E>(currentObject);
|
||||
BinaryNode<E> currentNode = root;
|
||||
currentNode.setData(currentObject);
|
||||
size = 1;
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right
|
||||
newNode.setParentAsRightChild(currentNode);
|
||||
}
|
||||
|
||||
currentNode = newNode;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo
|
||||
* che stampa le foglie dall'albero corrente (da sinistra verso destra)
|
||||
*/
|
||||
public void printLeaf() {
|
||||
printLeaf(root);
|
||||
}
|
||||
|
||||
public void printLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getLeft() == null && node.getRight() == null) System.out.println(node.getData().toString());
|
||||
else {
|
||||
printLeaf(node.getLeft());
|
||||
printLeaf(node.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che conta il numero
|
||||
* di foglie dell'albero corrente
|
||||
*/
|
||||
public int numberLeaf() {
|
||||
return numberLeaf(root);
|
||||
}
|
||||
|
||||
public int numberLeaf(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
if (node.getLeft() == null && node.getRight() == null) return 1;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : numberLeaf(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : numberLeaf(node.getRight());
|
||||
|
||||
return nLeft + nRight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Si aggiunga alla classe LinkedBinaryTree<E> un metodo che trasforma l'albero corrente
|
||||
* in modo che ogni suo nodo interno abbia esattamente due figli. Se un nodo ha solo un
|
||||
* figlio, si aggiunga l'altro nodo figlio come copia del figlio esistente
|
||||
*/
|
||||
public void makeFull() {
|
||||
makeFull(root);
|
||||
}
|
||||
|
||||
public void makeFull(BinaryNode<E> node) {
|
||||
if (node == null) return; // Se il nodo è nullo, non serve fare operazioni
|
||||
if (node.hasLeft() && node.hasRight()) return; // Se il nodo ha sia il figlio sinstro che destro, non serve fare operazioni
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package vettore_ordinabile;
|
||||
|
||||
public class VettoriIntero extends VettoreOrdinabile{
|
||||
|
||||
// Metodo costruttore default
|
||||
/*
|
||||
* Contiene solamente 10 elementi
|
||||
* */
|
||||
public VettoriIntero() {
|
||||
super(10);
|
||||
}
|
||||
|
||||
// Metodo costruttore custom
|
||||
/*
|
||||
* Contiene n elementi
|
||||
*/
|
||||
public VettoriIntero(int dimensioneMassima) {
|
||||
super(dimensioneMassima);
|
||||
}
|
||||
|
||||
// Metodo aggiungi
|
||||
/*
|
||||
* Questo metodo è un metodo bloccante in modo che
|
||||
* non aggiungino oggetti che non siano di tipo Integer
|
||||
*/
|
||||
public
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
ArrayList<Videogioco> giochi = new ArrayList<Videogioco>();
|
||||
|
||||
giochi.add(new Videogioco("The Last of Us Part II", "PS5", 2020, 39.99, 9));
|
||||
giochi.add(new Videogioco("Cyberpunk 2077", "PC", 2020, 29.99, 8));
|
||||
giochi.add(new Videogioco("Minecraft", "PC", 2011, 19.99, 10));
|
||||
giochi.add(new Videogioco("Ghost of Tsushima", "PS5", 2020, 49.99, 9));
|
||||
giochi.add(new Videogioco("Resident Evil 4 Remake", "PS5", 2023, 44.99, 9));
|
||||
giochi.add(new Videogioco("GTA V", "PC", 2013, 14.99, 8));
|
||||
giochi.add(new Videogioco("God of War Ragnarok", "PS5", 2022, 59.99, 10));
|
||||
giochi.add(new Videogioco("Fortnite", "PC", 2017, 0.0, 7));
|
||||
|
||||
// Ordina mediante Comparable - compareTo & stampa
|
||||
Collections.sort(giochi);
|
||||
printList(giochi);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private <T> void printList(List<T> lista) {
|
||||
System.out.print("{");
|
||||
for (int i = 0; i < lista.size(); i++) {
|
||||
System.out.print(" [");
|
||||
System.out.print(lista.get(i).toString());
|
||||
System.out.print("] ");
|
||||
}
|
||||
System.out.print("}");
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
ArrayList<Videogioco> giochi = new ArrayList<Videogioco>();
|
||||
|
||||
giochi.add(new Videogioco("The Last of Us Part II", "PS5", 2020, 39.99, 9));
|
||||
giochi.add(new Videogioco("Cyberpunk 2077", "PC", 2020, 29.99, 8));
|
||||
giochi.add(new Videogioco("Minecraft", "PC", 2011, 19.99, 10));
|
||||
giochi.add(new Videogioco("Ghost of Tsushima", "PS5", 2020, 49.99, 9));
|
||||
giochi.add(new Videogioco("Resident Evil 4 Remake", "PS5", 2023, 44.99, 9));
|
||||
giochi.add(new Videogioco("GTA V", "PC", 2013, 14.99, 8));
|
||||
giochi.add(new Videogioco("God of War Ragnarok", "PS5", 2022, 59.99, 10));
|
||||
giochi.add(new Videogioco("Fortnite", "PC", 2017, 0.0, 7));
|
||||
|
||||
// Per adoperare il comparable
|
||||
Collections.sort(giochi);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder();
|
||||
}
|
||||
|
||||
}
|
||||
+445
@@ -0,0 +1,445 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra.
|
||||
*
|
||||
* Nel metodo sono state inserite delle check con uno stack di
|
||||
* flag che permette di capire quando il nodo centrale è visitare
|
||||
* oppure no.
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
flags.add(false);
|
||||
}
|
||||
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.add(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itinorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR POST ORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso la logica è la seguente. si ha la
|
||||
* necessità di fare il seguente ciclo: SINISTRA -> DESTRA -> NODO CORRENTE
|
||||
*
|
||||
* Per simulare lo stack dobbiamo quindi ripercorrerlo al contrario,
|
||||
* dunque NODO CORRENTE -> DESTRA -> SINISTRA
|
||||
*
|
||||
* Possiamo dunque rifare lo stesso, di ciò che abbiamo fatto sopra.
|
||||
*/
|
||||
protected void itpostorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.push(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è ancora da visitare
|
||||
|
||||
// Visitiamo il nodo corrente
|
||||
queueOfNodes.push(current);
|
||||
flags.push(true);
|
||||
|
||||
// visitiamo il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.push(current.getRight());
|
||||
flags.push(false);
|
||||
}
|
||||
|
||||
// visitiamo il nodo di sinistra infine
|
||||
if (current.getLeft() != null) {
|
||||
queueOfNodes.push(current.getLeft());
|
||||
flags.push(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpostorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* II parziale 2022/2023
|
||||
* Realizzare un metodo costruttore della classe LinkedBinaryTree<E> che
|
||||
* prende in input una lista di oggetti di tipo E e costruisce una catena
|
||||
* casuale tale che l'iesimo elemento della lista è posizionato al livello iesimo
|
||||
* della catena e ogni nodo ha probabilità 1/2 di avere un figlio sinistro/destro.
|
||||
*/
|
||||
/*
|
||||
* Spiegazione intuitiva (visto che la melideo intende complicare la consegna):
|
||||
* Data ad esempio una lista del genere:
|
||||
* [A, B, C, D]
|
||||
*
|
||||
* Si ottiene quindi una catena del genere:
|
||||
* A
|
||||
* \
|
||||
* B
|
||||
* /
|
||||
* C
|
||||
* \
|
||||
* D
|
||||
*/
|
||||
public LinkedBinaryTree(List<E> objectList) {
|
||||
if (objectList == null) throw new NullPointerException();
|
||||
|
||||
Iterator<E> iterator = objectList.iterator();
|
||||
if (!iterator.hasNext()) return;
|
||||
|
||||
BinaryNode<E> currentNode = root;
|
||||
E currentObject = iterator.next();
|
||||
currentNode.setData(currentObject);
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
currentObject = iterator.next();
|
||||
int wing = (int) (Math.random() * 2);
|
||||
|
||||
BinaryNode<E> newNode = new BinaryNode<E>(currentObject);
|
||||
//newNode.setParent(currentNode);
|
||||
|
||||
if (wing == 0) {
|
||||
// Left Wing
|
||||
newNode.setParentAsLeftChild(currentNode);
|
||||
} else {
|
||||
// Right Wing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayListQueue<T> implements MyQueue<T> {
|
||||
|
||||
private List<T> queue = new ArrayList<T>();
|
||||
|
||||
@Override
|
||||
public boolean offer(T item) {
|
||||
return queue.add(item);
|
||||
}
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package vettore_ordinabile;
|
||||
|
||||
public abstract class VettoreOrdinabile {
|
||||
|
||||
// Variabili di istanza
|
||||
private Object[] vettore; // Vettore dove memorizzare i dati
|
||||
private int dimensioneMassima;
|
||||
private int dimensioneCorrente;
|
||||
|
||||
// Costruttore
|
||||
public VettoreOrdinabile(int dimensioneMassima) {
|
||||
if (dimensioneMassima < 0) throw new IllegalArgumentException("La dimensione non può essere negativa");
|
||||
this.dimensioneMassima = dimensioneMassima;
|
||||
}
|
||||
|
||||
// FUNZIONI DI ISTANZA
|
||||
|
||||
/**
|
||||
* Funzione aggiungi.
|
||||
* Permette di aggiungere un elemento se la dimensione lo permette.
|
||||
*/
|
||||
public boolean aggiungi(Object elemento) {
|
||||
if (elemento != null && dimensioneCorrente < dimensioneMassima) {
|
||||
vettore[dimensioneCorrente] = elemento;
|
||||
dimensioneCorrente++;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Funzione leggi.
|
||||
* Permette di leggere un elemento ad una determinata posizione.
|
||||
*/
|
||||
public Object leggi(int indice) {
|
||||
if (indice >= 0 && indice < dimensioneCorrente) {
|
||||
return vettore[indice];
|
||||
} else return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Funzione che restituisce la dimensione corrente
|
||||
*/
|
||||
public int dimensione() {
|
||||
return dimensioneCorrente;
|
||||
}
|
||||
|
||||
/**
|
||||
* Funzione che visualizza l'array
|
||||
*/
|
||||
public void visualizza() {
|
||||
this.ordina();
|
||||
for (int i = 0; i < this.dimensioneMassima; i++) {
|
||||
System.out.println(leggi(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Funzione che ordina l'array
|
||||
*/
|
||||
public void ordina() {
|
||||
for (int i = 0; i < dimensioneCorrente; i++) {
|
||||
int minimo = i;
|
||||
int j;
|
||||
for (j = i+1; j < dimensioneCorrente; j++) {
|
||||
if (confronta(vettore[minimo], vettore[j]) > 0) minimo = j;
|
||||
}
|
||||
Object temp = vettore[minimo];
|
||||
vettore[minimo] = vettore[j];
|
||||
vettore[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
// FUNZIONI ASTRATTE
|
||||
|
||||
/**
|
||||
* Funzione che restituisce il valore della comparazione
|
||||
*/
|
||||
protected abstract int confronta(Object elemento1, Object elemento2);
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
public class Videogioco implements Comparable<Videogioco>{
|
||||
|
||||
// Campi di istanza
|
||||
private String titolo;
|
||||
private String piattaforma;
|
||||
private Integer annoUscita;
|
||||
private Double prezzo;
|
||||
private Integer voto;
|
||||
|
||||
// Costruttore
|
||||
|
||||
private Videogioco() {}
|
||||
|
||||
public
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayListQueue<T> implements MyQueue<T> {
|
||||
|
||||
private List<T> queue = new ArrayList<T>();
|
||||
|
||||
@Override
|
||||
public boolean offer(T item) {
|
||||
return queue.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
return queue.removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peek() {
|
||||
return queue.getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return queue.getSize();
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null)
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package stack;
|
||||
|
||||
public class StackExample {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
MyStack<Character> stack = new ArrayListStack<Character>();
|
||||
|
||||
Character a = 'a';
|
||||
Character b = 'b';
|
||||
Character c = 'c';
|
||||
Character d = 'd';
|
||||
|
||||
stack.push(a);
|
||||
stack.push(b);
|
||||
stack.push(c);
|
||||
stack.push(d);
|
||||
|
||||
// Svuotiamo lo stack
|
||||
}
|
||||
|
||||
}
|
||||
+324
@@ -0,0 +1,324 @@
|
||||
package binary_tree;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Stack;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
temp.setData(null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean contains(E targetElement) {
|
||||
return find(targetElement, root) != null;
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del preorder.
|
||||
* Le regole per il preorder sono queste:
|
||||
* - Visita prima se stesso
|
||||
* - Poi visita tutto ciò che si trova sinistra
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void preorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
preorder(node.getLeft(), temporaryList);
|
||||
preorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPreOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
preorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE INORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo del inorder.
|
||||
* Le regole per l'inorder sono queste:
|
||||
* - Visita prima tutto ciò che si trova a sinistra
|
||||
* - Poi visita se stesso
|
||||
* - Infine visita tutto ciò che si trova a destra
|
||||
*/
|
||||
|
||||
protected void inorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
inorder(node.getLeft(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
|
||||
inorder(node.getRight(), temporaryList);
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
inorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE POSTORDER
|
||||
|
||||
/*
|
||||
* Qui si utilizza il metodo postorder.
|
||||
* Le regole per il postorder sono queste:
|
||||
* - Visita prima di tutto ciò che si trova a sinistra
|
||||
* - Poi visita tutto ciò che si trova a destra
|
||||
* - Infine visita il sestesso
|
||||
*/
|
||||
|
||||
protected void postorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
if (node == null) return;
|
||||
|
||||
postorder(node.getLeft(), temporaryList);
|
||||
postorder(node.getRight(), temporaryList);
|
||||
|
||||
if (node.getData() != null) temporaryList.add(node.getData());
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorPostOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
postorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE LEVEL ORDER
|
||||
|
||||
/*
|
||||
* Qui si usa il metodo levelorder.
|
||||
* Si analizza tutto il livello dell'albero.
|
||||
* Per chiarire di seguito un esempio:
|
||||
*
|
||||
* A
|
||||
* / \
|
||||
* B C
|
||||
* / \ \
|
||||
* D E F
|
||||
*
|
||||
* La lettura avviene quindi in questo modo:
|
||||
* A - B - C - D - E - F
|
||||
*
|
||||
* Si adopera una coda (Queue) di tipo FI-FO (First In - First Out)
|
||||
*/
|
||||
|
||||
protected void levelorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Queue<BinaryNode<E>> queueOfNodes = new LinkedList<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while(!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.remove();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
|
||||
if (current.getLeft() != null) queueOfNodes.add(current.getLeft());
|
||||
if (current.getRight() != null) queueOfNodes.add(current.getRight());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> iteratorLevelOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
levelorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATORE
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return iteratorPreOrder();
|
||||
}
|
||||
|
||||
// ITERATORE PREORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* In questo caso stiamo usando un tipo stack.
|
||||
* Dobbiamo di fatto simulare uno stack se vogliamo
|
||||
* iterativamente fare questa cosa.
|
||||
*
|
||||
* Perchè se prima dobbiamo visitare il nodo centrale,
|
||||
* poi il nodo a sinistra e poi il nodo a destra inseriamo
|
||||
* prima quello di destra e poi quello di sinistra?
|
||||
*
|
||||
* Lo stack di fatto è una coda LIFO, ovvero last in - first out
|
||||
* e quindi l'ultimo che entra è il primo che esce.
|
||||
*
|
||||
* dal momento che vale questa cosa, se facciamo entrare prima quello
|
||||
* di destra e poi quello di sinistra, il primo nodo che verrà
|
||||
* prelevato è ovviamente quello a sinistra.
|
||||
*/
|
||||
protected void itpreorder (BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
BinaryNode<E> current;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
// Come già spiegato pushamo prima il nodo di destra
|
||||
if (current.getRight() != null) queueOfNodes.push(current.getRight());
|
||||
// Infine aggiungiamo il nodo di sinistra
|
||||
if (current.getLeft() != null) queueOfNodes.push(current.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<E> ititeratorInOrder() {
|
||||
ArrayList<E> temporaryList = new ArrayList<E>();
|
||||
itpreorder(root, temporaryList);
|
||||
return temporaryList.iterator();
|
||||
}
|
||||
|
||||
// ITERATOR INORDER ITERATIVO (NON RICORSIVO)
|
||||
|
||||
/*
|
||||
* Questo metodo riguarda lo stesso di quello superiore.
|
||||
* Il metodo inorder richiede che si visiti prima sinistra,
|
||||
* poi il nodo stesso, infine il nodo di destra.
|
||||
*
|
||||
* Possiamo quindi sempre adoperare uno Stack per siumlare la
|
||||
* ricorsione.
|
||||
*
|
||||
* Come detto prima, se il primo nodo ad essere prelevato è
|
||||
* l'ultimo che si inserisce (coda LIFO, Stack) allora per simulare
|
||||
* sinistra -> centro -> destra, il primo nodo da inserire è quello di
|
||||
* destra
|
||||
*/
|
||||
private void itinorder(BinaryNode<E> node, List<E> temporaryList) {
|
||||
Stack<BinaryNode<E>> queueOfNodes = new Stack<BinaryNode<E>>();
|
||||
Stack<Boolean> flags = new Stack<Boolean>();
|
||||
|
||||
BinaryNode<E> current;
|
||||
Boolean flag;
|
||||
|
||||
queueOfNodes.add(node);
|
||||
flags.push(false);
|
||||
|
||||
while (!queueOfNodes.isEmpty()) {
|
||||
current = queueOfNodes.pop();
|
||||
flag = flags.pop();
|
||||
|
||||
if (flag) {
|
||||
// il nodo è da visitare
|
||||
if (current.getData() != null) temporaryList.add(current.getData());
|
||||
} else {
|
||||
// il nodo non è da visitare
|
||||
|
||||
// prima si aggiunge il nodo di destra
|
||||
if (current.getRight() != null) {
|
||||
queueOfNodes.add(current.getRight());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package parziale.p251110;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class Clinica {
|
||||
|
||||
ArrayList<Paziente> pazienti = new ArrayList<Paziente>();
|
||||
|
||||
// 1. Numero di pazienti Ricoverati
|
||||
public int pazientiRicoverati() {
|
||||
return pazienti.size();
|
||||
}
|
||||
|
||||
// 2. Inserimento del paziente
|
||||
/*
|
||||
* Dal momento che non ci è permesso adoperare
|
||||
* TreeSet per l'ordine e per l'unicità
|
||||
*/
|
||||
public boolean ricoveraPaziente(Paziente paziente) {
|
||||
// Se il paziente è nullo, nulla verrà aggiunto
|
||||
if (paziente == null) return false;
|
||||
|
||||
// Controllo se il paziente è già presente nella lista ricoveri
|
||||
Iterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
Paziente current = it.next();
|
||||
if (paziente.equals(current)) return false; // Se è già presente un paziente con id uguale allora non viene aggiunto e ritorna false
|
||||
}
|
||||
|
||||
// Aggiunta del paziente
|
||||
ListIterator<Paziente> it = pazienti.iterator();
|
||||
while (it.hasNext()) {
|
||||
Paziente current = it.next();
|
||||
int cmp = current.compareTo(paziente);
|
||||
if ()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package binary_tree;
|
||||
|
||||
public interface BinaryTree {
|
||||
|
||||
public boolean isEmpty();
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class TreeSetExample2 {
|
||||
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package vettore_ordinabile;
|
||||
|
||||
public class VettoriIntero extends VettoreOrdinabile{
|
||||
|
||||
// Metodo costruttore default
|
||||
/*
|
||||
* Contiene solamente 10 elementi
|
||||
* */
|
||||
public VettoriIntero() {
|
||||
super(10);
|
||||
}
|
||||
|
||||
// Metodo costruttore custom
|
||||
/*
|
||||
* Contiene n elementi
|
||||
*/
|
||||
public VettoriIntero(int dimensioneMassima) {
|
||||
super(dimensioneMassima);
|
||||
}
|
||||
|
||||
// Metodo aggiungi
|
||||
/*
|
||||
* Questo metodo è un metodo bloccante in modo che
|
||||
* non aggiungino oggetti che non siano di tipo Integer
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package stack;
|
||||
|
||||
public interface MyStack<T> {
|
||||
|
||||
/**
|
||||
* Aggiunge un elemento al top dello stack.
|
||||
* @param Elemento che deve essere aggiunto nello stack.
|
||||
*/
|
||||
void push(T item);
|
||||
|
||||
/**
|
||||
* Rimuove l'elemento al top dello stack.
|
||||
* @return
|
||||
*/
|
||||
T pop();
|
||||
|
||||
T peek();
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (this.parent == null) return null;
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode<E> {
|
||||
|
||||
// VARIABILI
|
||||
|
||||
private BinaryNode<E> left, right, parent;
|
||||
private E data;
|
||||
|
||||
// COSTRUTTORI
|
||||
|
||||
public BinaryNode(E data) {
|
||||
this.data = data;
|
||||
|
||||
left = right = parent = null;
|
||||
}
|
||||
|
||||
public BinaryNode(BinaryNode<E> left, E data, BinaryNode<E> right) {
|
||||
this.data = data;
|
||||
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
|
||||
this.parent = null;
|
||||
|
||||
if (this.left != null) this.left.parent = this;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public E getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public BinaryNode<E> getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isRoot() {
|
||||
return parent == null;
|
||||
}
|
||||
|
||||
public boolean isLeftChild() {
|
||||
return parent != null && parent.getLeft() == this;
|
||||
}
|
||||
|
||||
public boolean isRightChild() {
|
||||
return parent != null && parent.getRight() == this;
|
||||
}
|
||||
|
||||
public void setData(E data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setLeft(BinaryNode<E> left) {
|
||||
this.left = left;
|
||||
if (this.left != null) this.left.parent = this;
|
||||
}
|
||||
|
||||
public void setRight(BinaryNode<E> right) {
|
||||
this.right = right;
|
||||
if (this.right != null) this.right.parent = this;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsLeftChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldLeft = this.parent.left;
|
||||
this.parent.left = this;
|
||||
|
||||
return oldLeft;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setParentAsRightChild(BinaryNode<E> parent) {
|
||||
if (parent == null) return null;
|
||||
|
||||
this.parent = parent;
|
||||
BinaryNode<E> oldRight = this.parent.right;
|
||||
this.parent.right = this;
|
||||
|
||||
return oldRight;
|
||||
}
|
||||
|
||||
public BinaryNode<E> setAsRoot() {
|
||||
if (parent == null) return null;
|
||||
|
||||
BinaryNode<E> oldParent = parent;
|
||||
parent = null;
|
||||
|
||||
if (oldParent.left == this) oldParent.left = null;
|
||||
else oldParent.right = null;
|
||||
|
||||
return oldParent;
|
||||
}
|
||||
|
||||
public boolean hasLeft() {
|
||||
return left != null;
|
||||
}
|
||||
|
||||
public boolean hasRight() {
|
||||
return right != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) return false;
|
||||
if (other == this) return true;
|
||||
if (!(other instanceof BinaryNode<?>)) return false;
|
||||
|
||||
BinaryNode<?> otherType = (BinaryNode<?>)other;
|
||||
|
||||
if (!data.equals(otherType.data) || hasLeft() != otherType.hasLeft() || hasRight() != otherType.hasRight()) return false;
|
||||
if (this.left != null && !left.equals(otherType.left)) return false;
|
||||
if (this.right != null && !right.equals(otherType.right)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int levelOf() {
|
||||
int d = 0;
|
||||
BinaryNode<E> cur = this;
|
||||
|
||||
while (cur.parent != null){
|
||||
d++;
|
||||
cur = cur.parent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package jcf_set.example;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class TreeSetExample2 {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
TreeSet<String> tree1 = new TreeSet<String>();
|
||||
|
||||
tree1.add("yes");
|
||||
tree1.add("no");
|
||||
tree1.add("maybe");
|
||||
tree1.add("always");
|
||||
tree1.add("no");
|
||||
|
||||
System.out.println("Stampa del TreeSet1: ");
|
||||
System.out.println(tree1);
|
||||
|
||||
TreeSet<String> tree2 = new TreeSet<String>(tree1);
|
||||
|
||||
System.out.println("Stampa del TreeSet1: ");
|
||||
System.out.println(tree1);
|
||||
}
|
||||
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
leftTree.root.setAsRoot();
|
||||
|
||||
size = size - leftTree.size;
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeRight() {
|
||||
LinkedBinaryTree<E> rightTree = null;
|
||||
if (root.getRight() == null) return rightTree;
|
||||
|
||||
rightTree = new LinkedBinaryTree<E>();
|
||||
rightTree.root = root.getRight();
|
||||
rightTree.size = getSize(root.getRight());
|
||||
rightTree.root.setAsRoot();
|
||||
|
||||
size = size - rightTree.size;
|
||||
|
||||
return rightTree;
|
||||
}
|
||||
|
||||
protected BinaryNode<E> find(E targetElement, BinaryNode<E> root) {
|
||||
if (root == null) return null;
|
||||
if (root.getData().equals(targetElement)) return root;
|
||||
BinaryNode<E> resNode;
|
||||
resNode = find(targetElement, root.getLeft());
|
||||
if (resNode == null) resNode = find(targetElement, root.getRight());
|
||||
return resNode;
|
||||
}
|
||||
|
||||
public boolean remove(E targetElement) {
|
||||
if (targetElement == null) return false;
|
||||
BinaryNode<E> temp = find(targetElement, root);
|
||||
if (temp != null) {
|
||||
|
||||
} else return false;
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
ArrayList<Videogioco> giochi = new ArrayList<Videogioco>();
|
||||
|
||||
giochi.add(new Videogioco("The Last of Us Part II", "PS5", 2020, 39.99, 9));
|
||||
giochi.add(new Videogioco("Cyberpunk 2077", "PC", 2020, 29.99, 8));
|
||||
giochi.add(new Videogioco("Minecraft", "PC", 2011, 19.99, 10));
|
||||
giochi.add(new Videogioco("Ghost of Tsushima", "PS5", 2020, 49.99, 9));
|
||||
giochi.add(new Videogioco("Resident Evil 4 Remake", "PS5", 2023, 44.99, 9));
|
||||
giochi.add(new Videogioco("GTA V", "PC", 2013, 14.99, 8));
|
||||
giochi.add(new Videogioco("God of War Ragnarok", "PS5", 2022, 59.99, 10));
|
||||
giochi.add(new Videogioco("Fortnite", "PC", 2017, 0.0, 7));
|
||||
|
||||
// Per adoperare il comparable
|
||||
Collections.sort(giochi);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private <T> void printList(List<T> lista) {
|
||||
System.out.print("{");
|
||||
for (int i = 0; i < lista.size(); i++) {
|
||||
System.out.print
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package binary_tree;
|
||||
|
||||
public class BinaryNode {
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package parziale.p251110;
|
||||
|
||||
public class Paziente implements Comparable<Paziente> {
|
||||
|
||||
private String id;
|
||||
private int annoNascita;
|
||||
|
||||
public Paziente(
|
||||
String id,
|
||||
int annoNascita) {
|
||||
this.id = id;
|
||||
this.annoNascita = annoNascita;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getAnnoNascita() {
|
||||
return annoNascita;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) return false;
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Paziente)) return false;
|
||||
|
||||
Paziente p = (Paziente) o;
|
||||
|
||||
return id.equals(p.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Paziente p) {
|
||||
if (annoNascita < p.annoNascita) return -1;
|
||||
if (annoNascita > p.annoNascita) return 1;
|
||||
}
|
||||
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package binary_tree;
|
||||
|
||||
public class LinkedBinaryTree<E> implements BinaryTree<E>{
|
||||
|
||||
// VARIABILI D'INSTANZA
|
||||
private BinaryNode<E> root;
|
||||
private int size;
|
||||
|
||||
// Metodi costruttori
|
||||
public LinkedBinaryTree() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(E data) {
|
||||
root = new BinaryNode<E>(data);
|
||||
size = 1;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree(LinkedBinaryTree<E> left, E data, LinkedBinaryTree<E> right) {
|
||||
root = new BinaryNode<E>(left.root, data, right.root);
|
||||
size = 1 + left.size + right.size;
|
||||
}
|
||||
|
||||
// METODI
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public E getRoot() {
|
||||
if (isEmpty()) return null;
|
||||
return root.getData();
|
||||
}
|
||||
|
||||
public BinaryNode<E> getRootNode() {
|
||||
if (isEmpty()) return null;
|
||||
return root;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
root = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
private int getSize(BinaryNode<E> node) {
|
||||
if (node == null) return 0;
|
||||
|
||||
int nLeft = (node.getLeft() == null) ? 0 : getSize(node.getLeft());
|
||||
int nRight = (node.getRight() == null) ? 0 : getSize(node.getRight());
|
||||
|
||||
return 1 + nLeft + nRight;
|
||||
}
|
||||
|
||||
public LinkedBinaryTree<E> removeLeft() {
|
||||
LinkedBinaryTree<E> leftTree = null;
|
||||
if (root.getLeft() == null) return leftTree;
|
||||
|
||||
leftTree = new LinkedBinaryTree<E>();
|
||||
leftTree.root = root.getLeft();
|
||||
leftTree.size = getSize(root.getLeft());
|
||||
|
||||
return leftTree;
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package queue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayListQueue<T> implements MyQueue<T> {
|
||||
|
||||
private List<T> queue = new ArrayList<T>();
|
||||
|
||||
@Override
|
||||
public boolean offer(T item) {
|
||||
return queue.add(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove() {
|
||||
return queue.removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peek() {
|
||||
return queue.getFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return queue.size();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user