जावा में ट्री डेटा-संरचना को कैसे लागू किया जाए? [बन्द है]


496

जावा में एक पेड़ का प्रतिनिधित्व करने के लिए कोई मानक जावा पुस्तकालय वर्ग है?

विशेष रूप से मुझे निम्नलिखित का प्रतिनिधित्व करने की आवश्यकता है:

  • किसी भी नोड में उप-पेड़ में बच्चों की एक मनमानी संख्या हो सकती है
  • प्रत्येक नोड (रूट के बाद) और यह बच्चों के लिए स्ट्रिंग मान होगा
  • मुझे दिए गए नोड के सभी बच्चों (किसी प्रकार की सूची या स्ट्रिंग्स की सरणी) प्राप्त करने की आवश्यकता है और यह स्ट्रिंग मान है (यानी एक विधि जो इनपुट के रूप में नोड लेगी और आउटपुट के रूप में बच्चों के सभी स्ट्रिंग मानों को वापस कर देगी)

क्या इसके लिए कोई उपलब्ध संरचना है या क्या मुझे अपना स्वयं का निर्माण करने की आवश्यकता है (यदि ऐसा कार्यान्वयन सुझाव महान होगा)।


3
यदि आप जावा 8 का उपयोग कर रहे हैं, और अपने नोड्स को धाराओं, फ़िल्टरिंग, आदि के साथ पार करना चाहते हैं; तो आप ड्यूरियन github.com/diffplug/durian
नेड ट्विग

1
आप इस API का उपयोग कर सकते हैं: sourceforge.net/p/treeds4j
मोहम्मद एन्नहदी एल इदरीसी

जवाबों:


306

यहाँ:

public class Tree<T> {
    private Node<T> root;

    public Tree(T rootData) {
        root = new Node<T>();
        root.data = rootData;
        root.children = new ArrayList<Node<T>>();
    }

    public static class Node<T> {
        private T data;
        private Node<T> parent;
        private List<Node<T>> children;
    }
}

यह एक मूल वृक्ष संरचना है जिसका उपयोग Stringकिसी अन्य वस्तु के लिए किया जा सकता है । साधारण पेड़ों को लागू करने के लिए यह काफी आसान है कि आपको क्या चाहिए।

आपको जो कुछ भी जोड़ना है वह जोड़ने, हटाने, ट्रैवर्सिंग और कंस्ट्रक्टर्स के लिए तरीके हैं। का Nodeबेसिक बिल्डिंग ब्लॉक है Tree


304
कड़ाई से Treeकक्षा बोलना आवश्यक नहीं है, क्योंकि प्रत्येक Nodeको अपने आप में एक पेड़ के रूप में देखा जा सकता है।
जोआचिम सॉउर

34
@ जोआ, मुझे रूट को समाहित करने वाला एक ढांचा पसंद है। आप ट्री क्लास में उन तरीकों को जोड़ सकते हैं जो एक नोड के बजाय एक पेड़ पर कॉल करने के लिए अधिक समझदार हैं।
jjnguy

24
@ जस्टिन: उदाहरण के लिए? यह एक ईमानदार सवाल है: मैं एक भी विधि के बारे में नहीं सोच सकता जो पूरे पेड़ पर समझ में आता है जो एक उप-पेड़ पर समझ में नहीं आता है।
जोकिम सॉउर

22
मैं @ जोया से सहमत हूं कि ट्री क्लास जरूरी नहीं है। मैं पेड़ों की पुनरावर्ती प्रकृति को कोड में स्पष्ट रूप से छोड़ने के लिए पसंद करता हूं एक अलग ट्री क्लास नहीं जोड़कर और लगातार नोड वर्ग का उपयोग करके। इसके बजाय मैं एक चर 'ट्री' या 'रूट' का नाम देता हूं, अगर यह स्पष्ट होना चाहिए कि आप एक पेड़ के मूल नोड के साथ काम कर रहे हैं।
jvdbogae

89
@ जोआ एक चार साल का मैं आपसे पूरी तरह सहमत हूं। वृक्ष वर्ग निक्स।
jjnguy

122

अभी तक एक और पेड़ संरचना:

public class TreeNode<T> implements Iterable<TreeNode<T>> {

    T data;
    TreeNode<T> parent;
    List<TreeNode<T>> children;

    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
    }

    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }

    // other features ...

}

नमूना उपयोग:

TreeNode<String> root = new TreeNode<String>("root");
{
    TreeNode<String> node0 = root.addChild("node0");
    TreeNode<String> node1 = root.addChild("node1");
    TreeNode<String> node2 = root.addChild("node2");
    {
        TreeNode<String> node20 = node2.addChild(null);
        TreeNode<String> node21 = node2.addChild("node21");
        {
            TreeNode<String> node210 = node20.addChild("node210");
        }
    }
}

बोनस
पूरी तरह से पेड़ के साथ देखें:

  • इटरेटर
  • खोज कर
  • जावा / सी #

https://github.com/gt4dev/yet-another-tree-structure


2
बस अपनी लाइब्रेरी को बेहद उपयोगी पाया। धन्यवाद। लेकिन मैं जानना चाहता हूं कि माता-पिता और बच्चे के बीच संबंध संबंधों के आधार पर वृक्ष की संरचना को गतिशील रूप से कैसे लागू किया जाए। उदाहरण दिया गया है कि मेरे पास एक सदस्य 1 प्रायोजक एक और सदस्य 2, और सदस्य 2 प्रायोजक सदस्य 3 और इसी तरह के लिए है। पहले से ही टेबल रिकॉर्ड संबंध है लेकिन सिर्फ अनिश्चित मैं उन्हें अपने पुस्तकालय का उपयोग करके एक पेड़ में आबाद कर सकता हूं।
d4v1dv00 15

1
2016 तक, लिंक में कोई स्रोत फ़ाइल या डाउनलोड नहीं है
शेरोन बेन आशेर

2
मेरे विचार में, उपरोक्त उच्चतर उत्तर के तीन साल बाद, यह उत्तर क्लीनर है। हालाँकि, मैं LinkedList को इसके लिए एक ArrayList से बदल दूंगा। बच्चों के लिए।
आशा है कि

1
मैं बच्चों के लिए एक सेट का उपयोग करूंगा।
DPM

मैं गलत हो सकता हूं लेकिन ऐसा प्रतीत होता है कि इस कार्यान्वयन के साथ, आपको मान्य परिणाम प्राप्त hasNext()करने के next()लिए प्रत्येक कॉल से पहले कॉल करना होगा । यह Iteratorकल्पना का हिस्सा नहीं है ।
रॉबर्ट लुईस

97

वास्तव में JDK में कार्यान्वित एक बहुत अच्छी वृक्ष संरचना है।

पर एक नज़र डालें javax.swing.tree , TreeModel , और TreeNode । वे डिजाइन के साथ उपयोग करने के लिए डिज़ाइन किए गए JTreePanelहैं, लेकिन वे वास्तव में, एक बहुत अच्छा पेड़ कार्यान्वयन हैं और एक स्विंग इंटरफ़ेस के साथ इसका उपयोग करने से आपको कुछ भी नहीं रोक रहा है।

ध्यान दें कि जावा 9 के रूप में आप इन वर्गों का उपयोग नहीं करना चाहते हैं क्योंकि वे 'कॉम्पैक्ट प्रोफाइल' में मौजूद नहीं होंगे ।


5
हाँ, मैंने उन्हें अतीत में इस्तेमाल किया था, और वे एक पेड़ से जो कुछ भी चाहते हैं वह सब करेंगे। केवल नकारात्मक पक्ष मैं सोच सकता हूं कि उनके संबंधित कार्यान्वयन वर्गों के नामों की लंबाई है: DefaultTreeModel और DefaultMutableTreeNode। Verbose, लेकिन ऐसा नहीं है कि इसके सभी महत्वपूर्ण मुझे लगता है।
अंतिम गोब्बलमेंट

4
इसका सामना करने का अच्छा तरीका है कि स्टैटिक मेथड्स न्यूमॉडल () और न्यूकोड () और फिर स्टैटिक इम्पोर्ट के एक जोड़े का निर्माण किया जाए।
गैरेथ डेविस

140
मैं गैर-स्विंग-संबंधित कार्यों पर स्विंग लाइब्रेरीज़ का उपयोग करने से बचूंगा। यह खराब कोडिंग प्रथा है । आप कभी नहीं जानते कि स्विंग अपने पेड़ों को कैसे लागू करते हैं, उनकी निर्भरता क्या है और भविष्य में यह कैसे बदल सकता है। स्विंग एक यूटिलिटी लाइब्रेरी नहीं बल्कि यूआई लाइब्रेरी है।
जसोप

44
मुझे लगता है कि खराब कोडिंग अभ्यास थोड़ा कठोर है।
गैरेथ डेविस

51
javax.swing.tree.TreeModel एक सार्वजनिक इंटरफ़ेस है (बिल्कुल java.util.List की तरह) और इसमें असंगत परिवर्तन नहीं होंगे। एक अतिरिक्त लाभ यह है कि आप अपने पेड़ को विकसित करते समय आसानी से डिबग / कल्पना कर सकते हैं।
lbalazscs

45

इस बारे में क्या?

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

/**
  * @author ycoppel@google.com (Yohann Coppel)
  * 
  * @param <T>
  *          Object's type in the tree.
*/
public class Tree<T> {

  private T head;

  private ArrayList<Tree<T>> leafs = new ArrayList<Tree<T>>();

  private Tree<T> parent = null;

  private HashMap<T, Tree<T>> locate = new HashMap<T, Tree<T>>();

  public Tree(T head) {
    this.head = head;
    locate.put(head, this);
  }

  public void addLeaf(T root, T leaf) {
    if (locate.containsKey(root)) {
      locate.get(root).addLeaf(leaf);
    } else {
      addLeaf(root).addLeaf(leaf);
    }
  }

  public Tree<T> addLeaf(T leaf) {
    Tree<T> t = new Tree<T>(leaf);
    leafs.add(t);
    t.parent = this;
    t.locate = this.locate;
    locate.put(leaf, t);
    return t;
  }

  public Tree<T> setAsParent(T parentRoot) {
    Tree<T> t = new Tree<T>(parentRoot);
    t.leafs.add(this);
    this.parent = t;
    t.locate = this.locate;
    t.locate.put(head, this);
    t.locate.put(parentRoot, t);
    return t;
  }

  public T getHead() {
    return head;
  }

  public Tree<T> getTree(T element) {
    return locate.get(element);
  }

  public Tree<T> getParent() {
    return parent;
  }

  public Collection<T> getSuccessors(T root) {
    Collection<T> successors = new ArrayList<T>();
    Tree<T> tree = getTree(root);
    if (null != tree) {
      for (Tree<T> leaf : tree.leafs) {
        successors.add(leaf.head);
      }
    }
    return successors;
  }

  public Collection<Tree<T>> getSubTrees() {
    return leafs;
  }

  public static <T> Collection<T> getSuccessors(T of, Collection<Tree<T>> in) {
    for (Tree<T> tree : in) {
      if (tree.locate.containsKey(of)) {
        return tree.getSuccessors(of);
      }
    }
    return new ArrayList<T>();
  }

  @Override
  public String toString() {
    return printTree(0);
  }

  private static final int indent = 2;

  private String printTree(int increment) {
    String s = "";
    String inc = "";
    for (int i = 0; i < increment; ++i) {
      inc = inc + " ";
    }
    s = inc + head;
    for (Tree<T> child : leafs) {
      s += "\n" + child.printTree(increment + indent);
    }
    return s;
  }
}

5
इस वर्ग वस्तु का उपयोग करके बनाए गए पेड़ पर डीएफएस को कैसे लागू किया जाएगा?
leba-lev

3
इस वर्ग का उपयोग करके एक पत्ती को कैसे हटाया जाएगा?
गधस

2
हेड फील्ड का उपयोग किस लिए किया जाएगा?
Acour83

2
इस वर्ग के पास कुछ दस्तावेज होते तो बहुत अच्छा होता। मुझे यह समझ में नहीं आया कि क्या तरीके पसंद हैं setAsParentया getHeadक्या करते हैं और यह वह समय है जब मुझे वास्तव में पेड़ डेटा संरचनाओं पर कुछ मदद मिल सकती है। यहां तक ​​कि दस्तावेज़ के मूल स्रोत में कोई टिप्पणी नहीं है।
डिजास्टरकीड

23

मैंने एक छोटी सी लाइब्रेरी लिखी जो जेनेरिक पेड़ों को संभालती है। यह स्विंग के सामान की तुलना में बहुत अधिक हल्का है। मेरे पास इसके लिए एक मावेन प्रोजेक्ट भी है ।


3
मैं अब इसका उपयोग कर रहा हूं, शानदार ढंग से काम करता है। अपने स्वयं के अनुकूलन के लिए स्रोत को महत्वपूर्ण रूप से बदलना था, लेकिन यह एक महान शुरुआती बिंदु था। धन्यवाद विविन!
जसोप

20
public class Tree {
    private List<Tree> leaves = new LinkedList<Tree>();
    private Tree parent = null;
    private String data;

    public Tree(String data, Tree parent) {
        this.data = data;
        this.parent = parent;
    }
}

जाहिर है आप बच्चों को जोड़ने / हटाने के लिए उपयोगिता विधियाँ जोड़ सकते हैं।


1
इससे पता चलता है कि एक पेड़ का जनक एक पेड़ है। मेरा मानना ​​है कि आप ट्री नोड क्लास बनाने की कोशिश कर रहे थे।
मधुर भार्गव

16

आपको यह परिभाषित करके शुरू करना चाहिए कि पेड़ क्या है (डोमेन के लिए), यह सबसे पहले इंटरफ़ेस को परिभाषित करके किया जाता है । सभी पेड़ों की संरचनाएं संशोधित करने योग्य नहीं हैं, नोड्स को जोड़ने और हटाने में सक्षम होना एक वैकल्पिक विशेषता होनी चाहिए, इसलिए हम इसके लिए एक अतिरिक्त इंटरफ़ेस बनाते हैं।

नोड ऑब्जेक्ट्स बनाने की कोई आवश्यकता नहीं है जो मूल्यों को धारण करते हैं , वास्तव में मैं इसे एक प्रमुख डिजाइन दोष और अधिकांश पेड़ कार्यान्वयन में ओवरहेड के रूप में देखता हूं। यदि आप स्विंग को देखते हैं, तो TreeModelनोड वर्गों से मुक्त है (केवल DefaultTreeModelउपयोग करता है TreeNode), क्योंकि वे वास्तव में आवश्यक नहीं हैं।

public interface Tree <N extends Serializable> extends Serializable {
    List<N> getRoots ();
    N getParent (N node);
    List<N> getChildren (N node);
}

म्यूटेबल ट्री स्ट्रक्चर (नोड्स जोड़ने और हटाने की अनुमति देता है):

public interface MutableTree <N extends Serializable> extends Tree<N> {
    boolean add (N parent, N node);
    boolean remove (N node, boolean cascade);
}

इन इंटरफेस को देखते हुए, पेड़ों का उपयोग करने वाले कोड को इस बात की ज्यादा परवाह नहीं है कि पेड़ कैसे लागू किया जाता है। यह आपको जेनेरिक कार्यान्वयन के साथ-साथ विशिष्ट लोगों का उपयोग करने की अनुमति देता है, जहां आप किसी अन्य एपीआई के कार्यों को सौंपकर पेड़ का एहसास करते हैं।

उदाहरण: फ़ाइल ट्री संरचना

public class FileTree implements Tree<File> {

    @Override
    public List<File> getRoots() {
        return Arrays.stream(File.listRoots()).collect(Collectors.toList());
    }

    @Override
    public File getParent(File node) {
        return node.getParentFile();
    }

    @Override
    public List<File> getChildren(File node) {
        if (node.isDirectory()) {
            File[] children = node.listFiles();
            if (children != null) {
                return Arrays.stream(children).collect(Collectors.toList());
            }
        }
        return Collections.emptyList();
    }
}

उदाहरण: जेनेरिक ट्री संरचना (माता-पिता / बाल संबंधों पर आधारित):

public class MappedTreeStructure<N extends Serializable> implements MutableTree<N> {

    public static void main(String[] args) {

        MutableTree<String> tree = new MappedTreeStructure<>();
        tree.add("A", "B");
        tree.add("A", "C");
        tree.add("C", "D");
        tree.add("E", "A");
        System.out.println(tree);
    }

    private final Map<N, N> nodeParent = new HashMap<>();
    private final LinkedHashSet<N> nodeList = new LinkedHashSet<>();

    private void checkNotNull(N node, String parameterName) {
        if (node == null)
            throw new IllegalArgumentException(parameterName + " must not be null");
    }

    @Override
    public boolean add(N parent, N node) {
        checkNotNull(parent, "parent");
        checkNotNull(node, "node");

        // check for cycles
        N current = parent;
        do {
            if (node.equals(current)) {
                throw new IllegalArgumentException(" node must not be the same or an ancestor of the parent");
            }
        } while ((current = getParent(current)) != null);

        boolean added = nodeList.add(node);
        nodeList.add(parent);
        nodeParent.put(node, parent);
        return added;
    }

    @Override
    public boolean remove(N node, boolean cascade) {
        checkNotNull(node, "node");

        if (!nodeList.contains(node)) {
            return false;
        }
        if (cascade) {
            for (N child : getChildren(node)) {
                remove(child, true);
            }
        } else {
            for (N child : getChildren(node)) {
                nodeParent.remove(child);
            }
        }
        nodeList.remove(node);
        return true;
    }

    @Override
    public List<N> getRoots() {
        return getChildren(null);
    }

    @Override
    public N getParent(N node) {
        checkNotNull(node, "node");
        return nodeParent.get(node);
    }

    @Override
    public List<N> getChildren(N node) {
        List<N> children = new LinkedList<>();
        for (N n : nodeList) {
            N parent = nodeParent.get(n);
            if (node == null && parent == null) {
                children.add(n);
            } else if (node != null && parent != null && parent.equals(node)) {
                children.add(n);
            }
        }
        return children;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        dumpNodeStructure(builder, null, "- ");
        return builder.toString();
    }

    private void dumpNodeStructure(StringBuilder builder, N node, String prefix) {
        if (node != null) {
            builder.append(prefix);
            builder.append(node.toString());
            builder.append('\n');
            prefix = "  " + prefix;
        }
        for (N child : getChildren(node)) {
            dumpNodeStructure(builder, child, prefix);
        }
    }
}

1
जब मैं इस संरचना का पालन करता हूं तो मुझे एक समस्या का सामना करना पड़ता है जब मैं पेड़ करता हूं। "(" ए "," बी "); tree.add ("ए", "सी"); पेड़.दद ("सी", "डी"); tree.add ("ई", "ए"); E, A का एक अभिभावक है। हम यह कैसे करते हैं?
saikiks

1
हाय सैनिक्स, ऊपर दिए गए कोड में एक बग था जिसके कारण अंतिम संबंध नहीं जोड़ा गया था। यह अब तय हो गया है, और मैंने गैर-शून्य चेक और (अधिक महत्वपूर्ण) भी जोड़ा है: चक्रीय चेक जो पेड़ की संरचना का उल्लंघन करने से रोकता है (एक कोड या इसके पूर्वजों में से एक बच्चे के रूप में खुद को जोड़ना)। संकेत के लिए धन्यवाद!
पीटर वालसर

1
मैंने बग को ठीक कर दिया है अगर कोई भी उस बग के लिए एक फिक्स की तलाश कर रहा है जो आपको करना है, तो यह देखें कि क्या जोड़ें विधि गलत है और यदि यह गलत है तो बस एक अस्थायी नया लिंक्डहैशसेट बनाएं <N> और पेड़ के नोडेलिस्ट को क्लोन करें तो यू स्पष्ट हो सकता है पेड़, माता-पिता के नोड को जोड़ें जो पिछले चरण में जोड़ा नहीं गया था और फिर tempNode के सभी को वापस मूल पेड़ में जोड़ा गया ... हालांकि संरचना के लिए धन्यवाद!
saikiks 19

2
बस उन बेकार सार्वजनिक संशोधकों को अपने इंटरफेस से हटा दें ।
हमीद

1
मैं इससे एक json सरणी कैसे उत्पन्न कर सकता हूं
पवन पांडेय

12

कोई उत्तर में सरलीकृत लेकिन काम करने वाले कोड का उल्लेख नहीं है, इसलिए यहां यह है:

public class TreeNodeArray<T> {
    public T value;
    public final  java.util.List<TreeNodeArray<T>> kids =  new java.util.ArrayList<TreeNodeArray<T>>();
}

10

आप जावा के किसी भी XML API को डॉक्यूमेंट और Node के रूप में उपयोग कर सकते हैं..एक XML स्ट्रिंग्स के साथ एक ट्री स्ट्रक्चर है


5
उत्कृष्ट विचार, हम नोड्स की खोज करने के लिए dom4j + jaxen xpath का उपयोग करके मेमोरी XML स्कीमा में उपयोग कर सकते हैं।
बेन रुहमा ने

8

यदि आप व्हाइटबोर्ड कोडिंग, एक साक्षात्कार, या यहां तक ​​कि सिर्फ एक पेड़ का उपयोग करने की योजना बना रहे हैं, तो इन सभी की क्रिया बहुत कम है।

यह आगे कहा जाना चाहिए कि जिस कारण से एक पेड़ वहां नहीं है, जैसे, कहते हैं, Pair(जिसके बारे में कहा जा सकता है), ऐसा इसलिए है क्योंकि आपको इसका उपयोग करके कक्षा में अपने डेटा को इनकैप्सुलेट करना चाहिए, और सबसे सरल कार्यान्वयन जैसा दिखता है:

/***
/* Within the class that's using a binary tree for any reason. You could 
/* generalize with generics IFF the parent class needs different value types.
 */
private class Node {
  public String value;
  public Node[] nodes; // Or an Iterable<Node> nodes;
}

यह वास्तव में एक मनमाना चौड़ाई के पेड़ के लिए है।

यदि आप एक द्विआधारी पेड़ चाहते थे तो अक्सर नामित क्षेत्रों के साथ उपयोग करना आसान होता है:

private class Node { // Using package visibility is an option
  String value;
  Node left;
  Node right;
}

या यदि आप एक तिकड़ी चाहते थे:

private class Node {
  String value;
  Map<char, Node> nodes;
}

अब आपने कहा आप चाहते हैं

सभी बच्चों को प्राप्त करने में सक्षम होने के लिए (किसी प्रकार की सूची या स्ट्रिंग्स की सरणी) दिए गए नोड का प्रतिनिधित्व करने वाले इनपुट स्ट्रिंग दिए गए हैं

जो आपके होमवर्क जैसा लगता है।
लेकिन जब से मुझे यकीन है कि अब कोई भी समय सीमा बीत चुकी है ...

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

public class kidsOfMatchTheseDays {
 static private class Node {
   String value;
   Node[] nodes;
 }

 // Pre-order; you didn't specify.
 static public List<String> list(Node node, String find) {
   return list(node, find, new ArrayList<String>(), false);
 }

 static private ArrayList<String> list(
     Node node,
     String find,
     ArrayList<String> list,
     boolean add) {
   if (node == null) {
     return list;
   }
   if (node.value.equals(find)) {
     add = true;
   }
   if (add) {
     list.add(node.value);
   }
   if (node.nodes != null) {
     for (Node child: node.nodes) {
       list(child, find, list, add);
     }
   }
   return list;
 }

 public static final void main(String... args) {
   // Usually never have to do setup like this, so excuse the style
   // And it could be cleaner by adding a constructor like:
   //     Node(String val, Node... children) {
   //         value = val;
   //         nodes = children;
   //     }
   Node tree = new Node();
   tree.value = "root";
   Node[] n = {new Node(), new Node()};
   tree.nodes = n;
   tree.nodes[0].value = "leftish";
   tree.nodes[1].value = "rightish-leafy";
   Node[] nn = {new Node()};
   tree.nodes[0].nodes = nn;
   tree.nodes[0].nodes[0].value = "off-leftish-leaf";
   // Enough setup
   System.out.println(Arrays.toString(list(tree, args[0]).toArray()));
 }
}

यह आपको इस तरह उपयोग करता है:

$ java kidsOfMatchTheseDays leftish
[leftish, off-leftish-leaf]
$ java kidsOfMatchTheseDays root
[root, leftish, off-leftish-leaf, rightish-leafy]
$ java kidsOfMatchTheseDays rightish-leafy
[rightish-leafy]
$ java kidsOfMatchTheseDays a
[]

7

गैरेथ के जवाब के समान लाइनों के साथ, DefaultMutableTreeNode की जाँच करें । यह सामान्य नहीं है, लेकिन अन्यथा बिल को फिट करने के लिए लगता है। भले ही यह javax.swing पैकेज में है, यह किसी भी AWT या स्विंग कक्षाओं पर निर्भर नहीं करता है। वास्तव में, स्रोत कोड में वास्तव में टिप्पणी है// ISSUE: this class depends on nothing in AWT -- move to java.util?


लोल, तुम भी इस कक्षा में कैसे आए?
पचेरियर

7

जावा में ट्री डेटा संरचना के एक जोड़े हैं, जैसे कि JDK स्विंग में DefaultMutableTreeNode, स्टैनफोर्ड पार्सर पैकेज में ट्री और अन्य खिलौना कोड। लेकिन इनमें से कोई भी सामान्य उद्देश्य के लिए पर्याप्त छोटा नहीं है।

जावा-ट्री प्रोजेक्ट जावा में एक अन्य सामान्य-उद्देश्य ट्री डेटा संरचना प्रदान करने का प्रयास करता है। इस और दूसरों के बीच अंतर हैं

  • बिलकुल मुफ्त। आप इसे कहीं भी उपयोग कर सकते हैं (अपने गृहकार्य को छोड़कर: P)
  • छोटा लेकिन सामान्य पर्याप्त। मैंने डेटा संरचना की सभी चीज़ों को एक वर्ग फ़ाइल में रखा है, इसलिए कॉपी / पेस्ट करना आसान होगा।
  • सिर्फ एक खिलौना नहीं। मुझे दर्जनों जावा ट्री कोड्स की जानकारी है जो केवल बाइनरी ट्रीज़ या सीमित ऑपरेशंस को ही हैंडल कर सकते हैं। यह ट्रीनोड उससे कहीं अधिक है। यह नोड्स पर जाने के विभिन्न तरीके प्रदान करता है, जैसे कि प्रीऑर्डर, पोस्टऑर्डर, ब्रेडफर्स्ट, पत्तियां, रूट से रूट, आदि। इसके अलावा, पुनरावृत्तियों को भी पर्याप्तता के लिए प्रदान किया जाता है।
  • अधिक बर्तन जोड़े जाएंगे। मैं इस परियोजना को व्यापक बनाने के लिए और अधिक संचालन जोड़ने के लिए तैयार हूं, खासकर यदि आप गिटब के माध्यम से अनुरोध भेजते हैं।


5

चूंकि प्रश्न उपलब्ध डेटा संरचना के लिए पूछता है, लिस्ट या सरणियों से एक पेड़ का निर्माण किया जा सकता है:

Object[] tree = new Object[2];
tree[0] = "Hello";
{
  Object[] subtree = new Object[2];
  subtree[0] = "Goodbye";
  subtree[1] = "";
  tree[1] = subtree;
}

instanceof यह निर्धारित करने के लिए उपयोग किया जा सकता है कि क्या कोई तत्व एक उपप्रकार या टर्मिनल नोड है।


2
कुरूप। और काम नहीं करता है, अगर आपके डेटा ऑब्जेक्ट क्रमशः सूचियों में सरणियाँ हो सकते हैं।
user686249

1
मैं मानता हूं कि यह बदसूरत है। Objectरों या तो पत्ता वस्तुओं (उदाहरण के लिए, हो सकता है String) या शाखाओं (सरणियों द्वारा प्रतिनिधित्व)। और यह काम करता है: यह कोड संकलित करेगा, और यह Stringएस का एक छोटा पेड़ बनाता है ।
ओलाथे

5
public abstract class Node {
  List<Node> children;

  public List<Node> getChidren() {
    if (children == null) {
      children = new ArrayList<>();
    }
    return chidren;
  }
}

के रूप में सरल के रूप में यह हो जाता है और उपयोग करने के लिए बहुत आसान है। इसका उपयोग करने के लिए, इसे विस्तारित करें:

public class MenuItem extends Node {
  String label;
  String href;
  ...
}

3

उदाहरण के लिए :

import java.util.ArrayList;
import java.util.List;



/**
 * 
 * @author X2
 *
 * @param <T>
 */
public class HisTree<T> 
{
    private Node<T> root;

    public HisTree(T rootData) 
    {
        root = new Node<T>();
        root.setData(rootData);
        root.setChildren(new ArrayList<Node<T>>());
    }

}

class Node<T> 
{

    private T data;
    private Node<T> parent;
    private List<Node<T>> children;

    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public Node<T> getParent() {
        return parent;
    }
    public void setParent(Node<T> parent) {
        this.parent = parent;
    }
    public List<Node<T>> getChildren() {
        return children;
    }
    public void setChildren(List<Node<T>> children) {
        this.children = children;
    }
}

3

अतीत में मैंने इसके लिए केवल एक नेस्टेड मानचित्र का उपयोग किया है। यह वही है जो मैं आज का उपयोग करता हूं, यह बहुत सरल है लेकिन यह मेरी आवश्यकताओं के अनुरूप है। शायद यह एक और मदद करेगा।

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by kic on 16.07.15.
 */
public class NestedMap<K, V> {
    private final Map root = new HashMap<>();

    public NestedMap<K, V> put(K key) {
        Object nested = root.get(key);

        if (nested == null || !(nested instanceof NestedMap)) root.put(key, nested = new NestedMap<>());
        return (NestedMap<K, V>) nested;
    }

    public Map.Entry<K,V > put(K key, V value) {
        root.put(key, value);

        return (Map.Entry<K, V>) root.entrySet().stream().filter(e -> ((Map.Entry) e).getKey().equals(key)).findFirst().get();
    }

    public NestedMap<K, V> get(K key) {
        return (NestedMap<K, V>) root.get(key);
    }

    public V getValue(K key) {
        return (V) root.get(key);
    }

    @JsonValue
    public Map getRoot() {
        return root;
    }

    public static void main(String[] args) throws Exception {
        NestedMap<String, Integer> test = new NestedMap<>();
        test.put("a").put("b").put("c", 12);
        Map.Entry<String, Integer> foo = test.put("a").put("b").put("d", 12);
        test.put("b", 14);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(test));

        foo.setValue(99);
        System.out.println(mapper.writeValueAsString(test));

        System.out.println(test.get("a").get("b").getValue("d"));
    }
}

3

मैंने "HashMap" पर आधारित एक छोटा "ट्रीमैप" वर्ग लिखा है जो पथ जोड़ने का समर्थन करता है:

import java.util.HashMap;
import java.util.LinkedList;

public class TreeMap<T> extends LinkedHashMap<T, TreeMap<T>> {

    public void put(T[] path) {
        LinkedList<T> list = new LinkedList<>();
        for (T key : path) {
            list.add(key);
        }
        return put(list);
    }

    public void put(LinkedList<T> path) {
        if (path.isEmpty()) {
            return;
        }
        T key = path.removeFirst();
        TreeMap<T> val = get(key);
        if (val == null) {
            val = new TreeMap<>();
            put(key, val);
        }
        val.put(path);
    }

}

इसका उपयोग "टी" (जेनेरिक) प्रकार की चीजों के एक पेड़ को स्टोर करने के लिए किया जा सकता है, लेकिन इसमें नोड्स में अतिरिक्त डेटा संग्रहीत करने का समर्थन (अभी तक) नहीं है। यदि आपके पास इस तरह की फाइल है:

root, child 1
root, child 1, child 1a
root, child 1, child 1b
root, child 2
root, child 3, child 3a

फिर आप इसे निष्पादित करके एक पेड़ बना सकते हैं:

TreeMap<String> root = new TreeMap<>();
Scanner scanner = new Scanner(new File("input.txt"));
while (scanner.hasNextLine()) {
  root.put(scanner.nextLine().split(", "));
}

और आपको एक अच्छा पेड़ मिलेगा। अपनी आवश्यकताओं के अनुकूल होना आसान होना चाहिए।


2

आप HashTree का उपयोग कर सकते हैं Apache शामिल क्लास का जो जकार्ता प्रोजेक्ट का हिस्सा है।

हैशट्री क्लास को पैकेज में शामिल किया गया है। org.apache.jorphan.collections। हालाँकि यह पैकेज JMeter परियोजना के बाहर जारी नहीं किया गया है, आप इसे आसानी से प्राप्त कर सकते हैं:

1) JMeter स्रोत डाउनलोड करें

2) एक नया पैकेज बनाएं।

3) इस पर कॉपी करें / src / jorphan / org / apache / jorphan / collection /। Data.java को छोड़कर सभी फाइलें

4) कॉपी /src/jorphan/org/apache/jorphan/util/JOrphanUtils.java

5) हैशट्री का उपयोग करने के लिए तैयार है।


2

जावा में कोई विशिष्ट डेटा संरचना नहीं है जो आपकी आवश्यकताओं के अनुरूप हो। आपकी आवश्यकताएं काफी विशिष्ट हैं और इसके लिए आपको अपनी खुद की डेटा संरचना तैयार करनी होगी। अपनी आवश्यकताओं को देखते हुए कोई भी कह सकता है कि आपको कुछ विशिष्ट कार्यक्षमता वाले किसी प्रकार के एन-एरी ट्री की आवश्यकता है। आप अपनी डेटा संरचना को निम्नलिखित तरीके से डिज़ाइन कर सकते हैं:

  1. पेड़ के नोड की संरचना नोड और बच्चों की सूची में सामग्री की तरह होगी: कक्षा नोड {स्ट्रिंग मूल्य; बच्चों की सूची;}
  2. आपको किसी दिए गए स्ट्रिंग के बच्चों को पुनः प्राप्त करने की आवश्यकता है, इसलिए आपके पास 2 विधियाँ हो सकती हैं 1: नोड सर्चनोड (स्ट्रिंग स्ट्रिंग), उस नोड को लौटाएगा जिसमें दिए गए इनपुट के समान मूल्य है (खोज के लिए BFS का उपयोग करें) 2: सूची getCildren (स्ट्रिंग) str): यह विधि आंतरिक रूप से searchNode को कॉल करेगी ताकि नोड में समान स्ट्रिंग हो और फिर यह बच्चों के सभी स्ट्रिंग मानों की सूची बनाएगा और वापस आएगा।
  3. आपको पेड़ में स्ट्रिंग डालने की भी आवश्यकता होगी। आपको शून्य डालने (स्ट्रिंग अभिभावक, स्ट्रिंग मान) के लिए एक विधि लिखनी होगी: यह फिर से अभिभावक के बराबर मान वाले नोड को खोजेगा और फिर आप दिए गए मान के साथ एक नोड बना सकते हैं और पाए गए माता-पिता को बच्चों की सूची में जोड़ सकते हैं ।

मैं सुझाव दूंगा, आप कक्षा नोड {स्ट्रिंग मान जैसे एक वर्ग में नोड की संरचना लिखते हैं; बच्चों को सूचीबद्ध करें;} और अन्य सभी विधियों जैसे खोज, डालें और एक अन्य नोडलिल्स क्लास में मिल्ड्रिलन करें ताकि आप विशिष्ट पेड़ पर ऑपरेशन करने के लिए पेड़ की जड़ को भी पास कर सकें जैसे: कक्षा नोडोडिल्स {सार्वजनिक स्थैतिक नोड खोज (नोड रूट, स्ट्रिंग मूल्य) {बीएफएस करें और नोड लौटें}


2
    // TestTree.java
// A simple test to see how we can build a tree and populate it
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TestTree extends JFrame {

  JTree tree;
  DefaultTreeModel treeModel;

  public TestTree( ) {
    super("Tree Test Example");
    setSize(400, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public void init( ) {
    // Build up a bunch of TreeNodes. We use DefaultMutableTreeNode because the
    // DefaultTreeModel can use it to build a complete tree.
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("SubRoot");
    DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
    DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");

    // Build our tree model starting at the root node, and then make a JTree out
    // of it.
    treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);

    // Build the tree up from the nodes we created.
    treeModel.insertNodeInto(subroot, root, 0);
    // Or, more succinctly:
    subroot.add(leaf1);
    root.add(leaf2);

    // Display it.
    getContentPane( ).add(tree, BorderLayout.CENTER);
  }

  public static void main(String args[]) {
    TestTree tt = new TestTree( );
    tt.init( );
    tt.setVisible(true);
  }
}

3
कृपया कोड को डंप न करें - यह बताएं कि यह क्या करता है, और विशेष रूप से यह अन्य सभी उत्तरों की तुलना में अलग क्यों है (बेहतर है)।
५२ पर जन डॉगगेन

2

मैंने एक ट्री लाइब्रेरी लिखी है जो Java8 के साथ अच्छी तरह से खेलती है और इसकी कोई अन्य निर्भरता नहीं है। यह कार्यात्मक प्रोग्रामिंग से कुछ विचारों की एक ढीली व्याख्या भी प्रदान करता है और आपको पूरे पेड़ या उपप्रकारों को मैप / फ़िल्टर / प्रून / खोज करने देता है।

https://github.com/RutledgePaulV/prune

कार्यान्वयन अनुक्रमण के साथ कुछ विशेष नहीं करता है और मैं पुनरावृत्ति से नहीं भटका, इसलिए यह संभव है कि बड़े पेड़ों के प्रदर्शन में गिरावट आएगी और आप स्टैक को उड़ा सकते हैं। लेकिन अगर आप सभी की जरूरत है छोटे से मध्यम गहराई का एक सीधा पेड़ है, मुझे लगता है कि यह काफी अच्छी तरह से काम करता है। यह समानता का एक मान (मूल्य आधारित) परिभाषा प्रदान करता है और इसमें एक महत्वपूर्ण कार्यान्वयन भी होता है जिससे आप पेड़ की कल्पना कर सकते हैं!


1

कृपया नीचे दिए गए कोड की जांच करें, जहां मैंने संग्रह कक्षाओं का उपयोग किए बिना ट्री डेटा संरचनाओं का उपयोग किया है। कोड में बग / सुधार हो सकते हैं लेकिन कृपया इसे केवल संदर्भ के लिए उपयोग करें

package com.datastructure.tree;

public class BinaryTreeWithoutRecursion <T> {

    private TreeNode<T> root;


    public BinaryTreeWithoutRecursion (){
        root = null;
    }


    public void insert(T data){
        root =insert(root, data);

    }

    public TreeNode<T>  insert(TreeNode<T> node, T data ){

        TreeNode<T> newNode = new TreeNode<>();
        newNode.data = data;
        newNode.right = newNode.left = null;

        if(node==null){
            node = newNode;
            return node;
        }
        Queue<TreeNode<T>> queue = new Queue<TreeNode<T>>();
        queue.enque(node);
        while(!queue.isEmpty()){

            TreeNode<T> temp= queue.deque();
            if(temp.left!=null){
                queue.enque(temp.left);
            }else
            {
                temp.left = newNode;

                queue =null;
                return node;
            }
            if(temp.right!=null){
                queue.enque(temp.right);
            }else
            {
                temp.right = newNode;
                queue =null;
                return node;
            }
        }
        queue=null;
        return node; 


    }

    public void inOrderPrint(TreeNode<T> root){
        if(root!=null){

            inOrderPrint(root.left);
            System.out.println(root.data);
            inOrderPrint(root.right);
        }

    }

    public void postOrderPrint(TreeNode<T> root){
        if(root!=null){

            postOrderPrint(root.left);

            postOrderPrint(root.right);
            System.out.println(root.data);
        }

    }

    public void preOrderPrint(){
        preOrderPrint(root);
    }


    public void inOrderPrint(){
        inOrderPrint(root);
    }

    public void postOrderPrint(){
        inOrderPrint(root);
    }


    public void preOrderPrint(TreeNode<T> root){
        if(root!=null){
            System.out.println(root.data);
            preOrderPrint(root.left);
            preOrderPrint(root.right);
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BinaryTreeWithoutRecursion <Integer> ls=  new BinaryTreeWithoutRecursion <>();
        ls.insert(1);
        ls.insert(2);
        ls.insert(3);
        ls.insert(4);
        ls.insert(5);
        ls.insert(6);
        ls.insert(7);
        //ls.preOrderPrint();
        ls.inOrderPrint();
        //ls.postOrderPrint();

    }

}

2
" संग्रह कक्षाओं का उपयोग किए बिना " आह? तो क्यू कक्षा कहाँ से आती है? और जैसा कि ऊपर कहा गया है, यह एक द्विआधारी पेड़ है, पहली आवश्यकता (किसी भी बच्चे के नोड्स) में विफल रहा है।
फीलोहो

1

आप java.util में ट्रीसेट क्लास का उपयोग कर सकते हैं। *। यह बाइनरी सर्च ट्री की तरह काम कर रहा है, इसलिए यह पहले से ही हल है। ट्रीसेट क्लास इपर्टेबल, कलेक्शन और सेट इंटरफेस लागू करता है। आप एक सेट की तरह पुनरावृत्ति के साथ पेड़ के माध्यम से पार कर सकते हैं।

TreeSet<String> treeSet = new TreeSet<String>();
Iterator<String> it  = treeSet.Iterator();
while(it.hasNext()){
...
}

आप जावा डॉक और कुछ अन्य की जांच कर सकते हैं ।


-1

कस्टम ट्री कलेक्शन फ्रेमवर्क का उपयोग किए बिना ट्री का कार्यान्वयन। इसमें ट्री कार्यान्वयन में आवश्यक विभिन्न मौलिक ऑपरेशन शामिल हैं।

class Node {

    int data;
    Node left;
    Node right;

    public Node(int ddata, Node left, Node right) {
        this.data = ddata;
        this.left = null;
        this.right = null;      
    }

    public void displayNode(Node n) {
        System.out.print(n.data + " "); 
    }

}

class BinaryTree {

    Node root;

    public BinaryTree() {
        this.root = null;
    }

    public void insertLeft(int parent, int leftvalue ) {
        Node n = find(root, parent);
        Node leftchild = new Node(leftvalue, null, null);
        n.left = leftchild;
    }

    public void insertRight(int parent, int rightvalue) {
        Node n = find(root, parent);
        Node rightchild = new Node(rightvalue, null, null);
        n.right = rightchild;
    }

    public void insertRoot(int data) {
        root = new Node(data, null, null);
    }

    public Node getRoot() {
        return root;
    }

    public Node find(Node n, int key) {     
        Node result = null;

        if (n == null)
            return null;

        if (n.data == key)
            return n;

        if (n.left != null)
            result = find(n.left, key);

        if (result == null)
            result = find(n.right, key);

        return result;
    } 

    public int getheight(Node root){
        if (root == null)
            return 0;

        return Math.max(getheight(root.left), getheight(root.right)) + 1; 
    }

    public void printTree(Node n) {     
        if (n == null)
            return;

        printTree(n.left);
        n.displayNode(n);
        printTree(n.right);             
    }

}

11
यह एक द्विआधारी पेड़ है, यह ओपी की पहली आवश्यकता पर विफल रहता है ...
फ़िहलो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.