mac->arch
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/.metadata/
|
||||
@@ -1,4 +1,4 @@
|
||||
#Tue May 12 13:59:16 CEST 2026
|
||||
host=DESKTOP-ALBQHEK
|
||||
process-id=5624
|
||||
#Tue May 12 15:01:46 CEST 2026
|
||||
host=eslusarzs-MacBook-Pro.local
|
||||
process-id=23862
|
||||
user=eslusarz
|
||||
|
||||
+168
@@ -891,3 +891,171 @@ user global configuration and to define the default location to store repositori
|
||||
not correct please set the HOME environment variable and restart Eclipse. Otherwise Git for Windows and
|
||||
EGit might behave differently since they see different configuration options.
|
||||
This warning can be switched off on the Team > Git > Confirmations and Warnings preference page.
|
||||
!SESSION 2026-05-12 15:01:42.681 -----------------------------------------------
|
||||
eclipse.buildId=4.39.0.20260305-0817
|
||||
java.version=21.0.10
|
||||
java.vendor=Eclipse Adoptium
|
||||
BootLoader constants: OS=macosx, ARCH=aarch64, WS=cocoa, NL=it_IT
|
||||
Framework arguments: -product org.eclipse.epp.package.java.product -keyring /Users/eslusarz/.eclipse_keyring
|
||||
Command-line arguments: -os macosx -ws cocoa -arch aarch64 -product org.eclipse.epp.package.java.product -keyring /Users/eslusarz/.eclipse_keyring
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-05-12 15:01:43.636
|
||||
!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
|
||||
|
||||
!ENTRY org.eclipse.core.resources 2 10035 2026-05-12 15:01:46.121
|
||||
!MESSAGE The workspace exited with unsaved changes in the previous session; refreshing workspace to recover changes.
|
||||
|
||||
!ENTRY org.eclipse.core.resources 4 567 2026-05-12 15:01:46.173
|
||||
!MESSAGE Workspace restored, but some problems occurred.
|
||||
!SUBENTRY 1 org.eclipse.core.resources 4 567 2026-05-12 15:01:46.173
|
||||
!MESSAGE Could not read metadata for '.org.eclipse.egit.core.cmp'.
|
||||
!STACK 1
|
||||
org.eclipse.core.internal.resources.ResourceException(/.org.eclipse.egit.core.cmp)[567]: java.lang.Exception: The project description file (.project) for '.org.eclipse.egit.core.cmp' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
|
||||
at org.eclipse.core.internal.resources.ResourceException.provideStackTrace(ResourceException.java:42)
|
||||
at org.eclipse.core.internal.resources.ResourceException.<init>(ResourceException.java:38)
|
||||
at org.eclipse.core.internal.localstore.FileSystemResourceManager.read(FileSystemResourceManager.java:1015)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:1004)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:983)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restore(SaveManager.java:825)
|
||||
at org.eclipse.core.internal.resources.SaveManager.startup(SaveManager.java:1689)
|
||||
at org.eclipse.core.internal.resources.Workspace.startup(Workspace.java:2677)
|
||||
at org.eclipse.core.internal.resources.Workspace.open(Workspace.java:2369)
|
||||
at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:591)
|
||||
at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:1)
|
||||
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:947)
|
||||
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:1)
|
||||
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:257)
|
||||
at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:184)
|
||||
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:324)
|
||||
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:267)
|
||||
at org.eclipse.core.resources.ResourcesPlugin.start(ResourcesPlugin.java:565)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:838)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:1)
|
||||
at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:830)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:780)
|
||||
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1082)
|
||||
at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:394)
|
||||
at org.eclipse.osgi.container.Module.doStart(Module.java:643)
|
||||
at org.eclipse.osgi.container.Module.start(Module.java:500)
|
||||
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:528)
|
||||
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:122)
|
||||
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:620)
|
||||
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:353)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:418)
|
||||
at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:41)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findClass0(BundleLoader.java:523)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:439)
|
||||
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:195)
|
||||
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
|
||||
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:186)
|
||||
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
|
||||
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
|
||||
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
|
||||
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
|
||||
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
|
||||
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
|
||||
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
|
||||
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
|
||||
at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
|
||||
!SUBENTRY 2 org.eclipse.core.resources 4 567 2026-05-12 15:01:46.174
|
||||
!MESSAGE The project description file (.project) for '.org.eclipse.egit.core.cmp' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
|
||||
!STACK 0
|
||||
java.lang.Exception: The project description file (.project) for '.org.eclipse.egit.core.cmp' is missing. This file contains important information about the project. The project will not function properly until this file is restored.
|
||||
at org.eclipse.core.internal.resources.ResourceException.provideStackTrace(ResourceException.java:42)
|
||||
at org.eclipse.core.internal.resources.ResourceException.<init>(ResourceException.java:38)
|
||||
at org.eclipse.core.internal.localstore.FileSystemResourceManager.read(FileSystemResourceManager.java:1015)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:1004)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restoreMetaInfo(SaveManager.java:983)
|
||||
at org.eclipse.core.internal.resources.SaveManager.restore(SaveManager.java:825)
|
||||
at org.eclipse.core.internal.resources.SaveManager.startup(SaveManager.java:1689)
|
||||
at org.eclipse.core.internal.resources.Workspace.startup(Workspace.java:2677)
|
||||
at org.eclipse.core.internal.resources.Workspace.open(Workspace.java:2369)
|
||||
at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:591)
|
||||
at org.eclipse.core.resources.ResourcesPlugin$WorkspaceInitCustomizer.addingService(ResourcesPlugin.java:1)
|
||||
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:947)
|
||||
at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:1)
|
||||
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:257)
|
||||
at org.osgi.util.tracker.AbstractTracked.trackInitial(AbstractTracked.java:184)
|
||||
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:324)
|
||||
at org.osgi.util.tracker.ServiceTracker.open(ServiceTracker.java:267)
|
||||
at org.eclipse.core.resources.ResourcesPlugin.start(ResourcesPlugin.java:565)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:838)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl$2.run(BundleContextImpl.java:1)
|
||||
at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:830)
|
||||
at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:780)
|
||||
at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1082)
|
||||
at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:394)
|
||||
at org.eclipse.osgi.container.Module.doStart(Module.java:643)
|
||||
at org.eclipse.osgi.container.Module.start(Module.java:500)
|
||||
at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:528)
|
||||
at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:122)
|
||||
at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:620)
|
||||
at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:353)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:418)
|
||||
at org.eclipse.osgi.internal.loader.sources.SingleSourcePackage.loadClass(SingleSourcePackage.java:41)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findClass0(BundleLoader.java:523)
|
||||
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:439)
|
||||
at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:195)
|
||||
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
|
||||
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:186)
|
||||
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
|
||||
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
|
||||
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
|
||||
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
|
||||
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
|
||||
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
|
||||
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
|
||||
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
|
||||
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
|
||||
at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
|
||||
|
||||
!ENTRY ch.qos.logback.classic 1 0 2026-05-12 15:01:46.409
|
||||
!MESSAGE Logback config file: /Users/eslusarz/eclipse-workspace/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.7.101.20251017-1242.xml
|
||||
|
||||
!ENTRY org.eclipse.jdt.ui 4 0 2026-05-13 12:09:02.056
|
||||
!MESSAGE AbortCompilation computing hover information in Graph.java at offset 199
|
||||
!STACK 0
|
||||
org.eclipse.jdt.internal.compiler.problem.AbortCompilation:
|
||||
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:11585)
|
||||
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:11975)
|
||||
at org.eclipse.jdt.internal.compiler.parser.Parser.parse(Parser.java:11916)
|
||||
at org.eclipse.jdt.internal.compiler.parser.Parser.dietParse(Parser.java:10308)
|
||||
at org.eclipse.jdt.core.dom.CompilationUnitResolver.parse(CompilationUnitResolver.java:656)
|
||||
at org.eclipse.jdt.core.dom.CompilationUnitResolver.toCompilationUnit(CompilationUnitResolver.java:1432)
|
||||
at org.eclipse.jdt.core.dom.CompilationUnitResolver$ECJCompilationUnitResolver.toCompilationUnit(CompilationUnitResolver.java:109)
|
||||
at org.eclipse.jdt.core.dom.ASTParser.internalCreateASTCached(ASTParser.java:1412)
|
||||
at org.eclipse.jdt.core.dom.ASTParser.lambda$1(ASTParser.java:1291)
|
||||
at org.eclipse.jdt.internal.core.JavaModelManager.cacheZipFiles(JavaModelManager.java:5709)
|
||||
at org.eclipse.jdt.core.dom.ASTParser.internalCreateAST(ASTParser.java:1291)
|
||||
at org.eclipse.jdt.core.dom.ASTParser.createAST(ASTParser.java:933)
|
||||
at org.eclipse.jdt.core.manipulation.internal.javadoc.CoreJavadocContentAccessUtility.createAST(CoreJavadocContentAccessUtility.java:350)
|
||||
at org.eclipse.jdt.core.manipulation.internal.javadoc.CoreJavadocContentAccessUtility.getJavadocNode(CoreJavadocContentAccessUtility.java:318)
|
||||
at org.eclipse.jdt.core.manipulation.internal.javadoc.CoreJavadocAccess.javadoc2HTML(CoreJavadocAccess.java:423)
|
||||
at org.eclipse.jdt.core.manipulation.internal.javadoc.CoreJavadocAccess.getHTMLContentFromSource(CoreJavadocAccess.java:363)
|
||||
at org.eclipse.jdt.core.manipulation.internal.javadoc.CoreJavadocAccess.getHTMLContent(CoreJavadocAccess.java:229)
|
||||
at org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2.getHTMLContent(JavadocContentAccess2.java:49)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover.getHoverInfo(JavadocHover.java:794)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover.internalGetHoverInfo(JavadocHover.java:712)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover.getHoverInfo2(JavadocHover.java:704)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:165)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:131)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.JavaEditorTextHoverProxy.getHoverInfo2(JavaEditorTextHoverProxy.java:89)
|
||||
at org.eclipse.jface.text.TextViewerHoverManager$1.run(TextViewerHoverManager.java:155)
|
||||
Suppressed: java.lang.Throwable: Source line 9 :
|
||||
-----
|
||||
package network;
|
||||
|
||||
public interface Graph<Vertex, Wheight> implements Iterable<Vertex> {
|
||||
|
||||
public boolean containsVertex(Vertex vertex);
|
||||
|
||||
public boolean addVertex(Vertex vertex);
|
||||
|
||||
public boolean |removeVertex(Vertex vertex);
|
||||
-----
|
||||
at org.eclipse.jdt.internal.ui.util.SelectionUtil.logException(SelectionUtil.java:157)
|
||||
at org.eclipse.jdt.internal.ui.text.java.hover.BestMatchHover.getHoverInfo2(BestMatchHover.java:178)
|
||||
... 3 more
|
||||
|
||||
-491
@@ -1,491 +0,0 @@
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
-492
@@ -1,492 +0,0 @@
|
||||
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
@@ -1,30 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-494
@@ -1,494 +0,0 @@
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
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
@@ -1,31 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET
|
||||
}
|
||||
|
||||
}
|
||||
-500
@@ -1,500 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-502
@@ -1,502 +0,0 @@
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
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
@@ -1,26 +0,0 @@
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
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
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
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
|
||||
List.sort(giochi);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco3 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Prima ordina per piattaforma alfabetica.
|
||||
* Se la piattaforma è uguale, per anno
|
||||
* di uscita crescente
|
||||
* se l'anno è uguale, allora per titolo alfabetico
|
||||
*/
|
||||
@Override
|
||||
public int compare(Videogioco v1, Videogioco v2) {
|
||||
int cpm =
|
||||
}
|
||||
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
// Implementazione del metodo comparatore
|
||||
|
||||
/**
|
||||
* compareTo ordina per prezzo crescente
|
||||
*/
|
||||
}
|
||||
-515
@@ -1,515 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>(node.getRight().getData());
|
||||
node.setLeft(copy);
|
||||
copy.setParentAsLeftChild(node);
|
||||
} else {
|
||||
copy = new BinaryNode<E>(node.getLeft().getData());
|
||||
node.setRight(copy);
|
||||
copy.setParentAsRightChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
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);
|
||||
|
||||
// TREESET (ordinato)
|
||||
}
|
||||
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
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)) {
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
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() && )
|
||||
}
|
||||
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
ArrayList<Videogioco> giochi = new ArrayList<Videogioco>();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-503
@@ -1,503 +0,0 @@
|
||||
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
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-500
@@ -1,500 +0,0 @@
|
||||
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() {
|
||||
|
||||
}
|
||||
|
||||
public void makeFull(BinaryNode<E node) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
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
|
||||
System.out.println("ordina per prezzo crescente");
|
||||
Collections.sort(giochi);
|
||||
printList(giochi);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
System.out.println("Ordina i videogiochi per titolo alfabetico crescente");
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
printList(giochi);
|
||||
|
||||
// Ordina dal voto più alto al più basso
|
||||
System.out.println("Ordina dal voto più alto al più basso");
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
printList(giochi);
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
// Implementazione del metodo comparatore
|
||||
|
||||
/**
|
||||
* compareTo ordina per prezzo crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco videogioco) {
|
||||
|
||||
if (this.prezzo < videogioco.prezzo) return -1;
|
||||
if (this.prezzo > videogioco.prezzo) return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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 static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
// Implementazione del metodo comparatore
|
||||
|
||||
/**
|
||||
* compareTo ordina per prezzo crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco videogioco) {
|
||||
if (this.prezzo < videogioco.prezzo) return -1;
|
||||
if (this.prezzo > videogioco.prezzo) return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-511
@@ -1,511 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy =
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
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 (non ordinato)
|
||||
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);
|
||||
|
||||
// TREESET (ordinato)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
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
|
||||
System.out.println("ordina per prezzo crescente");
|
||||
Collections.sort(giochi);
|
||||
printList(giochi);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
printList(giochi);
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
// Implementazione del metodo comparatore
|
||||
|
||||
/**
|
||||
* compareTo ordina per prezzo crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco videogioco) {
|
||||
if (this.prezzo < videogioco.prezzo) return -1;
|
||||
if (this.prezzo > videogioco.prezzo) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
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();
|
||||
if (!iterator.hasNext()) return null;
|
||||
Integer maxValue = iterator.next();
|
||||
while (iterator.hasNext()) {
|
||||
Integer current = iterator.next();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-511
@@ -1,511 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
-491
@@ -1,491 +0,0 @@
|
||||
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 (node.getLeft() == null && node.getRight() == null) return 1;
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
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
|
||||
System.out.println("ordina per prezzo crescente");
|
||||
Collections.sort(giochi);
|
||||
printList(giochi);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
System.out.println("Ordina i videogiochi per titolo alfabetico crescente");
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
printList(giochi);
|
||||
|
||||
// Ordina dal voto più alto al più basso
|
||||
System.out.println("Ordina dal voto più alto al più basso");
|
||||
Collections.sort(giochi, new ComparatorVideogioco2());
|
||||
printList(giochi);
|
||||
|
||||
// Multi
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
new InteriRipetuti().run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET (non ordinato)
|
||||
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);
|
||||
|
||||
// TREESET (ordinato)
|
||||
Set<Integer> treeset = new TreeSet<Integer>(hashset);
|
||||
|
||||
// Stampa di treeset
|
||||
System.out.println("Treeset");
|
||||
for (Integer x : treeset) System.out.println(x + " ");
|
||||
System.out.println(); System.out.println(hashset);
|
||||
}
|
||||
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
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();
|
||||
if (!iterator.hasNext()) return null;
|
||||
Integer maxValue = iterator.next();
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
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.
|
||||
*/
|
||||
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco2 implements Comparator<Videogioco> {
|
||||
|
||||
public in compare() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-514
@@ -1,514 +0,0 @@
|
||||
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 è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>(node.getRight().getData());
|
||||
node.setLeft(copy);
|
||||
copy.setParentAsLeftChild(node);
|
||||
} else {
|
||||
copy = new BinaryNode<E>(node.getLeft().getData());
|
||||
node.setRight(copy);
|
||||
copy.setParentAsRightChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-512
@@ -1,512 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>(node.getRight().getData());
|
||||
node.setLeft(copy);
|
||||
} else {
|
||||
copy = new BinaryNode<E>(node.getLeft().getData());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-516
@@ -1,516 +0,0 @@
|
||||
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 è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>(node.getRight().getData());
|
||||
node.setLeft(copy);
|
||||
copy.setParentAsLeftChild(node);
|
||||
} else {
|
||||
copy = new BinaryNode<E>(node.getLeft().getData());
|
||||
node.setRight(copy);
|
||||
copy.setParentAsRightChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
|
||||
public Double prezzo() {
|
||||
return prezzo;
|
||||
}
|
||||
|
||||
public Integer voto() {
|
||||
return voto;
|
||||
}
|
||||
|
||||
// Implementazione del metodo comparatore
|
||||
|
||||
/**
|
||||
* compareTo ordina per prezzo crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco videogioco) {
|
||||
|
||||
}
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
-491
@@ -1,491 +0,0 @@
|
||||
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 (node.getLeft() == null && node.getRight()) return 1;
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco1 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Ordina i videogiochi per titolo alfabetico crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco v1, Videogioco v2) {
|
||||
return String.compareTo(v1.titolo(), v2.titolo());
|
||||
}
|
||||
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
-509
@@ -1,509 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
}
|
||||
|
||||
}
|
||||
-501
@@ -1,501 +0,0 @@
|
||||
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;
|
||||
if (node.hasLeft() && node.hasRight()) return;
|
||||
}
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
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 ()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
public class ComparatorVideogioco2 implements Comparator<Videogioco> {
|
||||
|
||||
}
|
||||
-493
@@ -1,493 +0,0 @@
|
||||
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
|
||||
*/
|
||||
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
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
|
||||
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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
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.
|
||||
*/
|
||||
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
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();
|
||||
if (!iterator.hasNext()) return null;
|
||||
Integer maxValue;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
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.
|
||||
*/
|
||||
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
package jcf_set.example;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class InteriRipetuti {
|
||||
|
||||
public static void main(String[] Args) {
|
||||
new InteriRipetuti().run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int N = 20;
|
||||
int MAX_INT = 50;
|
||||
|
||||
// HASHSET (non ordinato)
|
||||
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);
|
||||
|
||||
// TREESET (ordinato)
|
||||
Set<Integer> treeset = new TreeSet<Integer>(hashset);
|
||||
|
||||
// Stampa di treeset
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco3 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Prima ordina per piattaforma alfabetica.
|
||||
* Se la piattaforma è uguale, per anno
|
||||
* di uscita crescente
|
||||
* se l'anno è uguale, allora per titolo alfabetico
|
||||
*/
|
||||
@Override
|
||||
public int compare(Videogioco v1, Videogioco v2) {
|
||||
int cmp = v1.piattaforma().compareTo(v2.piattaforma());
|
||||
if (cmp == 0) return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
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
|
||||
System.out.println("ordina per prezzo crescente");
|
||||
Collections.sort(giochi);
|
||||
printList(giochi);
|
||||
|
||||
// Ordina i videogiochi per titolo alfabetico crescente
|
||||
System.out.println("Ordina i videogiochi per titolo alfabetico crescente");
|
||||
Collections.sort(giochi, new ComparatorVideogioco1());
|
||||
printList(giochi);
|
||||
|
||||
// Ordina dal voto più alto al più basso
|
||||
System.out.println("Ordina dal voto più alto al più basso");
|
||||
Collections.sort(giochi, new ComparatorVideogioco2());
|
||||
printList(giochi);
|
||||
|
||||
// Multi
|
||||
System.out.println("Multi");
|
||||
Collections.sort(giochi, new ComparatorVideogioco3());
|
||||
printList(giochi);
|
||||
|
||||
}
|
||||
|
||||
private static <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("}");
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
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();
|
||||
if (!iterator.hasNext()) return null;
|
||||
Integer maxValue = iterator.next();
|
||||
while (iterator.hasNext()) {
|
||||
Integer current = iterator.next();
|
||||
if (current > maxValue) maxValue = current;
|
||||
}
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco1 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Ordina i videogiochi per titolo alfabetico crescente
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Videogioco v1, Videogioco v2) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
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) {
|
||||
Integer maxValue;
|
||||
}
|
||||
|
||||
}
|
||||
-511
@@ -1,511 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>(node.getRight());
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-511
@@ -1,511 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>();
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco3 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Prima ordina per piattaforma alfabetica.
|
||||
* Se la piattaforma è uguale, per anno
|
||||
* di uscita crescente
|
||||
* se l'anno è uguale, allora per titolo alfabetico
|
||||
*/
|
||||
@Override
|
||||
public int compare(Videogioco v1, Videogioco v2) {
|
||||
int cmp = v1.piattaforma().compareTo(v2.piattaforma());
|
||||
if (cmp == 0) return cmp;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco3 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Prima ordina per piattaforma alfabetica.
|
||||
* Se la piattaforma è uguale, per anno
|
||||
* di uscita crescente
|
||||
* se l'anno è uguale, allora per titolo alfabetico
|
||||
*/
|
||||
@Override
|
||||
public int compare(Videogioco v1, Videogioco v2) {
|
||||
int cmp = v1.piattaforma().compareTo(v2.piattaforma());
|
||||
if (cmp == 0) return cmp;
|
||||
cmp = v1.annoUscita() - v2.annoUscita();
|
||||
if (cmp == 0) return cmp;
|
||||
}
|
||||
|
||||
}
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// Getter
|
||||
public String titolo() {
|
||||
return titolo;
|
||||
}
|
||||
|
||||
public String piattaforma() {
|
||||
return piattaforma;
|
||||
}
|
||||
|
||||
public Integer annoUscita() {
|
||||
return annoUscita;
|
||||
}
|
||||
}
|
||||
-506
@@ -1,506 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-504
@@ -1,504 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
//if ()
|
||||
}
|
||||
|
||||
}
|
||||
-511
@@ -1,511 +0,0 @@
|
||||
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
|
||||
if (!node.hasLeft() && !node.hasRight()) return; // Se il nodo è una foglia non ha bisogno di fare operazioni
|
||||
|
||||
BinaryNode<E> copy;
|
||||
|
||||
if (!node.hasLeft()) {
|
||||
// Si copia il figlio destro in quello sinistro
|
||||
copy = new BinaryNode<E>();
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package comparatori.videogioco;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class ComparatorVideogioco2 implements Comparator<Videogioco> {
|
||||
|
||||
/**
|
||||
* Ordina dal più alto al più basso
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int compare() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user