मैं आज एक साक्षात्कार के लिए गया था, जहां मैं एक द्विआधारी पेड़ क्रमानुसार करने को कहा गया। मैं एक सरणी-आधारित दृष्टिकोण जहां नोड मैं (स्तर-आदेश ट्रावर्सल की तादाद में) के बच्चों के बाईं बच्चे के लिए 2 * मैं सूचकांक में थे और 2 * i + 1 सही बच्चे के लिए लागू किया। साक्षात्कारकर्ता कम या ज्यादा खुश लग रहा था, लेकिन मैं सोच रहा हूँ क्या serialize वास्तव में इसका मतलब है? यह विशेष रूप से डिस्क के लिए लिख, या एक पेड़ भी सिर्फ एक लिंक की गई सूची में पेड़ मोड़ शामिल serializing हैं के लिए पेड़ सपाट से संबंधित है, का कहना है। इसके अलावा, हम कैसे एक (दोगुना) लिंक्ड सूची में पेड़ सपाट, और फिर इसे पुनर्निर्माण के बारे में जाना होगा? आप लिंक किए गए सूची से पेड़ की सटीक संरचना को पुन: कर सकते हैं?
बाइनरी ट्री क्रमानुसार करने के लिए कैसे
दृष्टिकोण 1: पेड़ डेटा searialize करने के लिए दोनों के लिए inorder और Preorder ट्रेवर्सल करो। पर de-क्रमबद्धता उपयोग प्री-ऑर्डर को और Inorder पर BST कर ठीक से पेड़ के रूप में।
> बी - -> सी प्री-ऑर्डर भले ही संरचना अलग हो सकता है के रूप में प्रतिनिधित्व किया जा सकता है आप दोनों क्योंकि एक की जरूरत है।
दृष्टिकोण 2: उपयोग # एक प्रहरी जहाँ बाईं या दाईं बच्चे रिक्त है के रूप में .....
कैसे एक में आदेश ट्रावर्सल प्रदर्शन और एक std :: सूची या अपनी पसंद जो पेड़ सपाट के अन्य कंटेनर में जड़ कुंजी और सभी नोड कुंजी लगाने के बारे में। फिर, बस std :: सूची या अपनी पसंद को बढ़ावा देने लाइब्रेरी का उपयोग कर के कंटेनर को क्रमानुसार।
रिवर्स सरल है और फिर एक द्विआधारी पेड़ से मानक प्रविष्टि का उपयोग पेड़ के पुनर्निर्माण। यह एक बहुत बड़े पेड़ लेकिन क्रम के लिए पूरी तरह से कुशल एक std :: सूची में पेड़ कन्वर्ट करने के लिए नहीं किया जा सकता हे (एन) ज्यादा से ज्यादा और पेड़ के पुनर्निर्माण के लिए हे (लॉग एन) ज्यादा से ज्यादा है।
मैं यह करने के लिए एक पेड़ मैं सिर्फ सी में कोडित ++ के रूप में मैं जावा से सेल्सियस तक ++ मेरी डेटाबेस परिवर्तित कर रहा हूँ क्रमानुसार करने के बारे में हूँ।
उन सभी लेख क्रमबद्धता भाग के बारे में ज्यादातर बात करते हैं। अक्रमांकन हिस्सा थोड़ा एक पास में करने के लिए मुश्किल है।
मैं भी अक्रमांकन के लिए एक कुशल समाधान लागू किया है।
समस्या: क्रमानुसार और एक द्विआधारी सकारात्मक संख्या युक्त वृक्ष deserialize।
क्रमबद्धता हिस्सा:
- अशक्त प्रतिनिधित्व करने के लिए 0 का प्रयोग करें।
- अग्रिम आदेश ट्रावर्सल का उपयोग कर पूर्णांक सूची को क्रमानुसार।
Deserialization हिस्सा:
- पूर्णांकों की सूची में ले जाता है और अक्रमांकन के लिए पुनरावर्ती सहायक विधि का उपयोग करता।
- पुनरावर्ती deserializer एक जोड़ी (BTNode नोड इंट nextIndexToRead) जहां नोड ट्री नोड अब तक का निर्माण किया है देता है, और nextIndexToRead अगले संख्या की स्थिति को संख्या के धारावाहिक सूची में पढ़ा जा रहा है।
नीचे जावा में कोड है:
public final class BinaryTreeSerializer
{
public static List<Integer> Serialize(BTNode root)
{
List<Integer> serializedNums = new ArrayList<Integer>();
SerializeRecursively(root, serializedNums);
return serializedNums;
}
private static void SerializeRecursively(BTNode node, List<Integer> nums)
{
if (node == null)
{
nums.add(0);
return;
}
nums.add(node.data);
SerializeRecursively(node.left, nums);
SerializeRecursively(node.right, nums);
}
public static BTNode Deserialize(List<Integer> serializedNums)
{
Pair pair = DeserializeRecursively(serializedNums, 0);
return pair.node;
}
private static Pair DeserializeRecursively(List<Integer> serializedNums, int start)
{
int num = serializedNums.get(start);
if (num == 0)
{
return new Pair(null, start + 1);
}
BTNode node = new BTNode(num);
Pair p1 = DeserializeRecursively(serializedNums, start + 1);
node.left = p1.node;
Pair p2 = DeserializeRecursively(serializedNums, p1.startIndex);
node.right = p2.node;
return new Pair(node, p2.startIndex);
}
private static final class Pair
{
BTNode node;
int startIndex;
private Pair(BTNode node, int index)
{
this.node = node;
this.startIndex = index;
}
}
}
public class BTNode
{
public int data;
public BTNode left;
public BTNode right;
public BTNode(int data)
{
this.data = data;
}
}
सबसे अच्छा तरीका है एक विशेष चार प्रहरी के रूप में (# की तरह के रूप में पिछली टिप्पणी में उल्लेख किया है) का प्रयोग है। यह एक inorder ट्रावर्सल सरणी और अग्रिम आदेश / क्रंमोत्तर चंक्रमण सरणी के निर्माण की तुलना में बेहतर है, दोनों अंतरिक्ष जटिलता बुद्धिमान और समय जटिलता बुद्धिमान में। यह भी जिस तरह से लागू करने के लिए आसान है।
लिंक्ड सूची एक अच्छा फिट यहाँ आदेश पेड़ फिर से संगठित करने में के बाद से नहीं है, तो आप बेहतर स्थिरांक तत्व पहुँच समय है
पूर्व आदेश ट्रावर्सल का उपयोग करना, द्विआधारी पेड़ को क्रमानुसार। पेड़ deserialize करने के लिए एक ही पूर्व आदेश ट्रावर्सल का प्रयोग करें। बढ़त मामलों के बारे में सावधान रहें। यहाँ अशक्त नोड्स द्वारा "#" प्रतिनिधित्व कर रहे हैं
public static String serialize(TreeNode root){
StringBuilder sb = new StringBuilder();
serialize(root, sb);
return sb.toString();
}
private static void serialize(TreeNode node, StringBuilder sb){
if (node == null) {
sb.append("# ");
} else {
sb.append(node.val + " ");
serialize(node.left, sb);
serialize(node.right, sb);
}
}
public static TreeNode deserialize(String s){
if (s == null || s.length() == 0) return null;
StringTokenizer st = new StringTokenizer(s, " ");
return deserialize(st);
}
private static TreeNode deserialize(StringTokenizer st){
if (!st.hasMoreTokens())
return null;
String val = st.nextToken();
if (val.equals("#"))
return null;
TreeNode root = new TreeNode(Integer.parseInt(val));
root.left = deserialize(st);
root.right = deserialize(st);
return root;
}
मैं इसे का सार प्राप्त करने की कोशिश की है। तो यहाँ मेरी जावा कार्यान्वयन है। जैसा कि बताया जा इस एक द्विआधारी पेड़ नहीं एक BST है। serializing के लिए, में अग्रिम आदेश ट्रावर्सल आसान काम करने (शून्य नोड्स के लिए "शून्य" के साथ एक स्ट्रिंग के लिए) लगता है। प्रत्यावर्तन कॉल की एक पूरी उदाहरण के साथ नीचे कोड की जांच करें। deserializing के लिए, स्ट्रिंग एक LinkedList जहां निकालें (0) एक हे (1) समय चलाने में शीर्ष तत्व हो जाता है में बदल जाती है। भी deserializing के लिए कोड की टिप्पणियों में पूर्ण उदाहरण देखें। आशा है कि मदद मिलेगी की तुलना में मैं प्रत्येक विधि के लिए :) समग्र समय चल रहा है किया कोई कम संघर्ष (क्रमानुसार और deserialize) द्विआधारी पेड़ ट्रेवर्सल, यानी, हे (एन) जहां n नोड्स की संख्या है (प्रविष्टियों) के लिए एक ही समय चल रहा है पेड़ में
आयात java.util.LinkedList; आयात java.util.List;
सार्वजनिक वर्ग SerDesBinTree {
public static class TreeEntry<T>{
T element;
TreeEntry<T> left;
TreeEntry<T> right;
public TreeEntry(T x){
element = x;
left = null;
right = null;
}
}
TreeEntry<T> root;
int size;
StringBuilder serSB = new StringBuilder();
List<String> desList = new LinkedList<>();
public SerDesBinTree(){
root = null;
size = 0;
}
public void traverseInOrder(){
traverseInOrder(this.root);
}
public void traverseInOrder(TreeEntry<T> node){
if (node != null){
traverseInOrder(node.left);
System.out.println(node.element);
traverseInOrder(node.right);
}
}
public void serialize(){
serialize(this.root);
}
/*
* 1
* / \
* 2 3
* /
* 4
*
* ser(1)
* serSB.append(1) serSB: 1
* ser(1.left)
* ser(1.right)
* |
* |
* ser(1.left=2)
* serSB.append(2) serSB: 1, 2
* ser(2.left)
* ser(2.right)
* |
* |
* ser(2.left=null)
* serSB.append(NULL) serSB: 1, 2, NULL
* return
* |
* ser(2.right=null)
* serSB.append(NULL) serSB: 1, 2, NULL, NULL
* return
*
* |
* ser(1.right=3)
* serSB.append(3) serSB: 1, 2, NULL, NULL, 3
* ser(3.left)
* ser(3.right)
*
* |
* ser(3.left=4)
* serSB.append(4) serSB: 1, 2, NULL, NULL, 3, 4
* ser(4.left)
* ser(4.right)
*
* |
* ser(4.left=null)
* serSB.append(NULL) serSB: 1, 2, NULL, NULL, 3, 4, NULL
* return
*
* ser(4.right=null)
* serSB.append(NULL) serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL
* return
*
* ser(3.right=null)
* serSB.append(NULL) serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
* return
*
*/
public void serialize(TreeEntry<T> node){
// preorder traversal to build the string
// in addition: NULL will be added (to make deserialize easy)
// using StringBuilder to append O(1) as opposed to
// String which is immutable O(n)
if (node == null){
serSB.append("NULL,");
return;
}
serSB.append(node.element + ",");
serialize(node.left);
serialize(node.right);
}
public TreeEntry<T> deserialize(TreeEntry<T> newRoot){
// convert the StringBuilder into a list
// so we can do list.remove() for the first element in O(1) time
String[] desArr = serSB.toString().split(",");
for (String s : desArr){
desList.add(s);
}
return deserialize(newRoot, desList);
}
/*
* 1
* / \
* 2 3
* /
* 4
*
* deser(root, list) list: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
* root = new TreeEntry(1) list: 2, NULL, NULL, 3, 4, NULL, NULL, NULL
* root.left = deser(root.left, list) // **
* root.right = deser(root.right, list) // *-*
* return root // ^*^
*
*
* so far subtree
* 1
* / \
* null null
*
* deser(root.left, list)
* root.left = new TreeEntry(2) list: NULL, NULL, 3, 4, NULL, NULL, NULL
* root.left.left = deser(root.left.left, list) // ***
* root.left.right = deser(root.left.right, list) // ****
* return root.left // eventually return new TreeEntry(2) to ** above after the two calls are done
*
* so far subtree
* 2
* / \
* null null
*
* deser(root.left.left, list)
* // won't go further down as the next in list is NULL
* return null // to *** list: NULL, 3, 4, NULL, NULL, NULL
*
* so far subtree (same, just replacing null)
* 2
* / \
* null null
*
* deser(root.left.right, list)
* // won't go further down as the next in list is NULL
* return null // to **** list: 3, 4, NULL, NULL, NULL
*
* so far subtree (same, just replacing null)
* 2
* / \
* null null
*
*
* so far subtree // as node 2 completely returns to ** above
* 1
* / \
* 2 null
* / \
* null null
*
*
* deser(root.right, list)
* root.right = new TreeEntry(3) list: 4, NULL, NULL, NULL
* root.right.left = deser(root.right.left, list) // *&*
* root.right.right = deser(root.right.right, list) // *---*
* return root.right // eventually return to *-* above after the previous two calls are done
*
* so far subtree
* 3
* / \
* null null
*
*
* deser(root.right.left, list)
* root.right.left = new TreeEntry(4) list: NULL, NULL, NULL
* root.right.left.left = deser(root.right.left.left, list) // *(*
* root.right.left.right = deser(root.right.left.right, list) // *)*
* return root.right.left // to *&*
*
* so far subtree
* 4
* / \
* null null
*
* deser(root.right.left.left, list)
* // won't go further down as the next in list is NULL
* return null // to *(* list: NULL, NULL
*
* so far subtree (same, just replacing null)
* 4
* / \
* null null
*
* deser(root.right.left.right, list)
* // won't go further down as the next in list is NULL
* return null // to *)* list: NULL
*
*
* so far subtree (same, just replacing null)
* 4
* / \
* null null
*
*
* so far subtree
* 3
* / \
* 4 null
* / \
* null null
*
*
* deser(root.right.right, list)
* // won't go further down as the next in list is NULL
* return null // to *---* list: empty
*
* so far subtree (same, just replacing null of the 3 right)
* 3
* / \
* 4 null
* / \
* null null
*
*
* now returning the subtree rooted at 3 to root.right in *-*
*
* 1
* / \
* / \
* / \
* 2 3
* / \ / \
* null null / null
* /
* 4
* / \
* null null
*
*
* finally, return root (the tree rooted at 1) // see ^*^ above
*
*/
public TreeEntry<T> deserialize(TreeEntry<T> node, List<String> desList){
if (desList.size() == 0){
return null;
}
String s = desList.remove(0); // efficient operation O(1)
if (s.equals("NULL")){
return null;
}
Integer sInt = Integer.parseInt(s);
node = new TreeEntry<T>((T)sInt);
node.left = deserialize(node.left, desList);
node.right = deserialize(node.right, desList);
return node;
}
public static void main(String[] args) {
/*
* 1
* / \
* 2 3
* /
* 4
*
*/
SerDesBinTree<Integer> tree = new SerDesBinTree<>();
tree.root = new TreeEntry<Integer>(1);
tree.root.left = new TreeEntry<Integer>(2);
tree.root.right = new TreeEntry<Integer>(3);
tree.root.right.left = new TreeEntry<Integer>(4);
//tree.traverseInOrder();
tree.serialize();
//System.out.println(tree.serSB);
tree.root = null;
//tree.traverseInOrder();
tree.root = tree.deserialize(tree.root);
//tree.traverseInOrder();
// deserialize into a new tree
SerDesBinTree<Integer> newTree = new SerDesBinTree<>();
newTree.root = tree.deserialize(newTree.root);
newTree.traverseInOrder();
}
}
यहाँ द्विआधारी पेड़ serializing (संशोधित) के स्तर का आदेश ट्रावर्सल का उपयोग करने का एक और तरीका है। [बस पेस्ट कॉपी, यह काम करता है] सभी असंतुलित, संतुलित, सही विषम, छोड़ दिया विषम पेड़ कवर।
class TreeNode():
def __init__(self, val):
self.val = val
self.left = None
self.right = None
def getHeight(root):
if root == None:
return 0
return max(getHeight(root.left), getHeight(root.right)) + 1
treeArray = []
def levelOrderTraversal(root, level, numOfNodes):
if level <= 0 and numOfNodes <=0:
return
numOfNodes -= 1
if root != None and level == 1:
treeArray.append(root.val)
elif root == None and level == 1:
treeArray.append("$")
if root != None:
levelOrderTraversal(root.left, level-1, numOfNodes)
levelOrderTraversal(root.right, level-1, numOfNodes)
else:
levelOrderTraversal(root, level-1, numOfNodes)
levelOrderTraversal(root, level-1, numOfNodes)
def treeToIntArray(root):
h = getHeight(root)
for i in range(1, h+1):
levelOrderTraversal(root,i, i*2)
return treeArray
def intArrayToTree():
n = len(treeArray)
treeArrayOfObjects = [0]*len(treeArray)
for i in range(n):
if treeArray[i] != "$":
root = TreeNode(treeArray[i])
treeArrayOfObjects[i] = root
#Linking the child nodes
for i in range(n):
if treeArray[i] != "$":
root = treeArrayOfObjects[i]
if 2 * i + 1 < n:
root.left = treeArrayOfObjects[2*i + 1]
if 2 * i + 2 < n:
root.right = treeArrayOfObjects[2*i + 2]
treeArray[i] = root
return treeArrayOfObjects[0]
"""
root = TreeNode(7)
root.left = TreeNode(3)
root.right = TreeNode(9)
root.left.left = TreeNode(1)
root.left.right = None
root.right.left = None
root.right.right = TreeNode(4)
"""
root = TreeNode(7)
root.right = TreeNode(9)
root.right.right = TreeNode(4)
root.right.right.right = TreeNode(5)
print treeToIntArray(root)
root = intArrayToTree()
print root.val
print root.right.val
print root.right.right.val
print root.right.right.right.val
यहाँ पायथन में एक देर से जवाब है। यह (गहराई पहले) से अग्रिम आदेश क्रमबद्धता का उपयोग करता है और की सूची लौटाता है strings। Deserialization पेड़ देता है।
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
# This method serializes the tree into a string
def serialize(root):
vals = []
def encode(node):
vals.append(str(node.val))
if node.left is not None:
encode(node.left)
else:
vals.append("L")
if node.right is not None:
encode(node.right)
else:
vals.append("R")
encode(root)
print(vals)
return vals
# This method deserializes the string back into the tree
def deserialize(string_list):
def create_a_tree(sub_list):
if sub_list[0] == 'L' or sub_list[0] == 'R':
del sub_list[0]
return
parent = Node(sub_list[0])
del sub_list[0]
parent.left = create_a_tree(sub_list)
parent.right = create_a_tree(sub_list)
return parent
if len(string_list) != 0:
root_node = create_a_tree(string_list)
else:
print("ERROR - empty string!")
return 0
return root_node
परीक्षा करना:
tree1 = Node('root', Node('left'), Node('right'))
t = deserialize(serialize(tree1))
print(str(t.right.val))
क्रमबद्धता बिट्स के अनुक्रम में एक डेटा संरचना या वस्तु परिवर्तित इतना है कि यह एक फ़ाइल या स्मृति बफर में संग्रहित किया जा सकता है, या एक नेटवर्क कनेक्शन लिंक पर आसानी से ट्रांसमिट एक ही या किसी अन्य कंप्यूटर वातावरण में बाद में फिर से बनाया जा करने के लिए की प्रक्रिया है।
Deserialization स्ट्रिंग मूल वृक्ष संरचना करने के लिए वापस परिवर्तित करने की प्रक्रिया है।
क्रमबद्धता और अक्रमांकन की अवधारणा बहुत क्या एक संकलक कोड करने के लिए करता है के समान है। वहाँ पूरे संकलन प्रक्रिया में कई चरण होते हैं लेकिन हम इसे अमूर्त रखने की कोशिश करेंगे।
कोड का एक टुकड़ा को देखते हुए, संकलक टोकन में विभिन्न अच्छी तरह से परिभाषित घटकों टूट जाता है (उदाहरण के लिए, पूर्णांक एक टोकन है, डबल एक और टोकन है, {, एक टोकन है} एक और टोकन, आदि) है। [संकलन का सार स्तर का प्रदर्शन करने के लिए लिंक] [1]।
क्रमबद्धता: हम एक स्ट्रिंग के लिए पेड़ serializing के लिए अग्रिम आदेश ट्रावर्सल तर्क का उपयोग करें। हम "एक्स" जोड़ने के एक अशक्त सूचक / एक वृक्ष के नोड निरूपित करने के लिए होगा। इसके अलावा, मन में हमारे अक्रमांकन तर्क रखने के लिए, हम इतना है कि deserialization प्रक्रिया के साथ प्रत्येक नोड मूल्य विभाजन का उपयोग कर सकते हर धारावाहिक नोड मूल्य के बाद जोड़ने के लिए "," "," की जरूरत है।
Leetcode लिंक: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
वापस द्वारा स्पष्टीकरण SWE यूट्यूब चैनल वापस करने के लिए : https://www.youtube.com/watch?v=suj1ro8TIVY
For example:
You may serialize the following tree:
1
/ \
2 3
/ \
4 5
as "[1,2,null,null,3,4,null,null,5,null,null,]"
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null)
return "X,";
String leftSerialized = serialize(root.left);
String rightSerialized = serialize(root.right);
return root.val + "," + leftSerialized + rightSerialized;
}
private TreeNode deserializeHelper(Queue<String> queue)
{
String nodeValue = queue.poll();
if(nodeValue.equals("X"))
return null;
TreeNode newNode = new TreeNode(Integer.valueOf(nodeValue));
newNode.left = deserializeHelper(queue);
newNode.right = deserializeHelper(queue);
return newNode;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
Queue<String> queue = new LinkedList<>();
queue.addAll(Arrays.asList(data.split(",")));
return deserializeHelper(queue);
}
}
//Codec object will be instantiated and called as such:
//Codec codec = new Codec();
//codec.deserialize(codec.serialize(root));
मैं प्री-ऑर्डर उपयोग नहीं कर रहा है, लेकिन मैं BFS उपयोग कर रहा हूँ। इस से एक सवाल है leetcode
कार्यान्वयन के लोगों के अधिकांश गलत जब प्री-ऑर्डर का उपयोग कर रहे हैं: अपेक्षित परिणाम होना चाहिए
"[1,2,3, अशक्त, अशक्त, 4,5]", लेकिन इसके बजाय बहुमत लोगों के रूप में उत्पादन "[1,2,3, अशक्त, अशक्त, 4,5, अशक्त, अशक्त]" प्रिंट के बाद से वे कर रहे हैं स्तरों गिनती नहीं।
यहाँ सही परिणाम के साथ अपने कार्यान्वयन है।
class Node(object):
def __init__(self,data):
self.left = None
self.right = None
self.data = data
def serialize(root):
queue = [(root,0)]
result = []
max_level_with_value = 0
while queue:
(node,l) = queue.pop(0)
if node:
result.append((node.data,l))
queue.extend([(node.left,l+1),
(node.right,l+1)
])
max_level_with_value = max(max_level_with_value,l)
else:
result.append(('null',l))
filter_redundant(result,max_level_with_value)
def filter_redundant(result,max_level_with_value):
for v,l in result:
if l<= max_level_with_value:
print(v)
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.right.left = Node(4)
root.right.right = Node(5)
serialize(root)













