j'essaie d'imprimer tous les chemins d'accès racine à feuille dans un arbre binaire en utilisant Java.
public void printAllRootToLeafPaths(Node node,ArrayList path)
{
if(node==null)
{
return;
}
path.add(node.data);
if(node.left==null && node.right==null)
{
System.out.println(path);
return;
}
else
{
printAllRootToLeafPaths(node.left,path);
printAllRootToLeafPaths(node.right,path);
}
}
En méthode principale:
bst.printAllRootToLeafPaths(root, new ArrayList());
Mais sa donne une mauvaise sortie.
arbre donné:
5
/ \
/ \
1 8
\ /\
\ / \
3 6 9
Production attendue:
[5, 1, 3]
[5, 8, 6]
[5, 8, 9]
Mais la sortie a produit:
[5, 1, 3]
[5, 1, 3, 8, 6]
[5, 1, 3, 8, 6, 9]
Quelqu'un peut-il comprendre ...
Appelez les méthodes récursives avec:
printAllRootToLeafPaths(node.left, new ArrayList(path));
printAllRootToLeafPaths(node.right, new ArrayList(path));
Que se passe-t-il lorsque vous passez la path
(au lieu de new ArrayList(path)
, vous utilisez un seul objet dans toutes les méthodes appelées, ce qui signifie que, lorsque vous revenez à l'appelant d'origine, l'objet n'est pas dans le même état qu'il était.
Il vous suffit de créer un nouvel objet et de l'initialiser aux valeurs d'origine. De cette façon, l'objet d'origine n'est pas modifié.
Vous passez votre liste de manière récursive, mais il s’agit d’un objet mutable. Tous les appels le modifieront (en appelant List.add
) et modifieront vos résultats. Essayez de cloner/copier l'argument path
vers tous les appels récursifs pour fournir à chaque branche (harhar) son propre contexte.
public void PrintAllPossiblePath(Node node,List<Node> nodelist)
{
if(node != null)
{
nodelist.add(node);
if(node.left != null)
{
PrintAllPossiblePath(node.left,nodelist);
}
if(node.right != null)
{
PrintAllPossiblePath(node.right,nodelist);
}
else if(node.left == null && node.right == null)
{
for(int i=0;i<nodelist.size();i++)
{
System.out.print(nodelist.get(i)._Value);
}
System.out.println();
}
nodelist.remove(node);
}
}
nodelist.remove(node)
est la clé, il supprime l'élément une fois qu'il a imprimé le chemin respectif
vous pouvez faire de cette façon aussi. voici mon code Java.
public void printPaths(Node r,ArrayList arr)
{
if(r==null)
{
return;
}
arr.add(r.data);
if(r.left==null && r.right==null)
{
printlnArray(arr);
}
else
{
printPaths(r.left,arr);
printPaths(r.right,arr);
}
arr.remove(arr.size()-1);
}
Voici la bonne implémentation
public static <T extends Comparable<? super T>> List<List<T>> printAllPaths(BinaryTreeNode<T> node) {
List <List<T>> paths = new ArrayList<List<T>>();
doPrintAllPaths(node, paths, new ArrayList<T>());
return paths;
}
private static <T extends Comparable<? super T>> void doPrintAllPaths(BinaryTreeNode<T> node, List<List<T>> allPaths, List<T> path) {
if (node == null) {
return ;
}
path.add(node.getData());
if (node.isLeafNode()) {
allPaths.add(new ArrayList<T>(path));
} else {
doPrintAllPaths(node.getLeft(), allPaths, path);
doPrintAllPaths(node.getRight(), allPaths, path);
}
path.remove(node.getData());
}
Voici le cas de test
@Test
public void printAllPaths() {
BinaryTreeNode<Integer> bt = BinaryTreeUtil.<Integer>fromInAndPostOrder(new Integer[]{4,2,5,6,1,7,3}, new Integer[]{4,6,5,2,7,3,1});
List <List<Integer>> paths = BinaryTreeUtil.printAllPaths(bt);
assertThat(paths.get(0).toArray(new Integer[0]), equalTo(new Integer[]{1, 2, 4}));
assertThat(paths.get(1).toArray(new Integer[0]), equalTo(new Integer[]{1, 2, 5, 6}));
assertThat(paths.get(2).toArray(new Integer[0]), equalTo(new Integer[]{1, 3, 7}));
for (List<Integer> list : paths) {
for (Integer integer : list) {
System.out.print(String.format(" %d", integer));
}
System.out.println();
}
}
1 2 4 1 2 5 6 1 3 7
/* Given a binary tree, print out all of its root-to-leaf
paths, one per line. Uses a recursive helper to do the work.*/
void printPaths(Node node)
{
int path[] = new int[1000];
printPathsRecur(node, path, 0);
}
/* Recursive helper function -- given a node, and an array containing
the path from the root node up to but not including this node,
print out all the root-leaf paths. */
void printPathsRecur(Node node, int path[], int pathLen)
{
if (node == null)
return;
/* append this node to the path array */
path[pathLen] = node.data;
pathLen++;
/* it's a leaf, so print the path that led to here */
if (node.left == null && node.right == null)
printArray(path, pathLen);
else
{
/* otherwise try both subtrees */
printPathsRecur(node.left, path, pathLen);
printPathsRecur(node.right, path, pathLen);
}
}
/* Utility that prints out an array on a line */
void printArray(int ints[], int len)
{
int i;
for (i = 0; i < len; i++)
System.out.print(ints[i] + " ");
System.out.println("");
}
Nous pouvons utiliser la récursion pour y parvenir. La bonne structure de données le rend concis et efficace.
List<LinkedList<Tree>> printPath(Tree root){
if(root==null)return null;
List<LinkedList<Tree>> leftPath= printPath(root.left);
List<LinkedList<Tree>> rightPath= printPath(root.right);
for(LinkedList<Tree> t: leftPath){
t.addFirst(root);
}
for(LinkedList<Tree> t: rightPath){
t.addFirst(root);
}
leftPath.addAll(rightPath);
return leftPath;
}
J'ai essayé ce problème avec une ArrayList
et mon programme imprimait des chemins similaires.
J'ai donc modifié ma logique pour qu'elle fonctionne correctement en maintenant une count
interne, voici comment je l'ai faite.
private void printPaths(BinaryNode node, List<Integer> paths, int endIndex) {
if (node == null)
return;
paths.add(endIndex, node.data);
endIndex++;
if (node.left == null && node.right == null) {
//found the leaf node, print this path
printPathList(paths, endIndex);
} else {
printPaths(node.left, paths, endIndex);
printPaths(node.right, paths, endIndex);
}
}
public void printPaths() {
List<Integer> paths = new ArrayList<>();
printPaths(root, paths, 0);
}