Cum serializa binar copac

voturi
23

M-am dus la un interviu astăzi, în cazul în care am fost rugat să serializam un arbore binar. Am implementat o abordare bazată pe matrice în cazul în care copiii din nodul i (numerotare în nivelul de ordinul parcurgeri) au fost la 2 * indicele i pentru copil stânga și 2 * i + 1 pentru copil dreapta. Intervievatorul părea mai mult sau mai puțin mulțumit, dar mă întreb ce anume înseamnă serializare? Are se referă în mod specific la aplatizare copac pentru scrierea pe disc, sau ar serializarea un copac, de asemenea, doar includ transformarea copac într-o listă legată, să zicem. De asemenea, cum vom merge despre aplatizare copac într-o listă (de două ori), legat, și apoi reconstruind-l? Poți recrea structura exactă a arborelui din lista legată?

Întrebat 06/01/2011 la 04:48
sursa de către utilizator
În alte limbi...                            


10 răspunsuri

voturi
6

Abordarea 1: Nu atât Inorder și pentru precomandă parcurgeri la searialize datele de copac. La utilizarea de-serializarea de pre-comandă și de a face BST Inorder pentru a forma în mod corespunzător copac.

Ai nevoie de ambele pentru că A -> B -> C poate fi reprezentat ca precomandă, chiar dacă structura poate fi diferită.

Abordarea 2: Utilizați # ca santinelă copilul ori de câte ori la stânga sau la dreapta este nul .....

Publicat 23/02/2013 la 20:49
sursa de către utilizator

voturi
0

Cum despre efectuarea unei parcurgeri în ordine și pune cheia de bază și toate cheile nod într-o std :: listă sau alt container de alegere, care aplatizează copac. Apoi, pur și simplu serialize std :: lista sau containerul de alegere folosind biblioteca impuls.

Reversul este simplu și apoi reconstrui arborele folosind inserare standard, la un arbore binar. Acest lucru nu poate fi în întregime eficient pentru un copac foarte mare, dar runtime pentru a converti copac într-o std :: Lista este O (n), cel mult și pentru a reconstrui arborele este O (log n) cel mult.

Sunt pe cale de a face acest lucru pentru a serializa un copac am codat în C ++ ca eu sunt de conversie de la baza mea de date Java la C ++.

Publicat 12/03/2013 la 18:59
sursa de către utilizator

voturi
12

Toate aceste articole vorbesc mai ales despre partea serializare. Partea deserializarea este puțin dificil de a face într-o singură trecere.

Am implementat o soluție eficientă pentru deserializarea prea.

Problemă: serialize și deserializati un arbore binar care conține numere pozitive.

parte serializare:

  1. Utilizați 0 pentru a reprezenta nul.
  2. Serializa la lista de numere întregi folosind precomandă traversal.

parte deserializarea:

  1. Ia în lista de numere întregi și utilizează metoda de ajutor recursiv pentru deserializarea.
  2. deserializare recursive returnează o pereche (nod BTNode, int nextIndexToRead) în cazul în care nodul este nod copac construit până în prezent, și nextIndexToRead este poziția de numărul următor pentru a fi citite în lista serializate numerelor.

Mai jos este codul în Java:

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;
    }
}
Publicat 24/08/2013 la 21:28
sursa de către utilizator

voturi
0

Cel mai bun mod este de a utiliza un caracter special (cum ar fi # ca comentariu anterior menționat) ca santinelă. Este mai bine decât construirea unei parcurgeri matrice inordine si un traversal matrice precomandă / postordine, atât în ​​complexitate spațiu înțelept și complexitate timp înțelept. este, de asemenea, mod mai ușor de implementat.

Lista de legat nu este o alegere bună aici, deoarece, în scopul de a reconstrui copac, mai bine ai avea timp de acces element de const

Publicat 19/03/2014 la 23:07
sursa de către utilizator

voturi
2

Utilizarea pre parcurgeri comanda, serializa arbore binar. Utilizați aceeași traversal ordine prestabilită a deserializati copac. Fii atent cu privire la cazurile de margine. Aici nodurile nule sunt reprezentate de „#“

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;
    } 
Publicat 18/01/2016 la 17:56
sursa de către utilizator

voturi
0

Am fost încercarea de a obține esențialul. Deci, aici este punerea în aplicare meu Java. După cum sa menționat, acest lucru este un arbore binar nu un BST. Pentru serializarea, o precomandă traversal pare a fi de lucru mai ușor (la un șir de caractere, cu „NULL“ pentru nodurile nule). Vă rugăm să verificați codul de mai jos, cu un exemplu complet de apeluri recursivitate. Pentru deserializing, șirul este convertit la un LinkedList unde elimina (0) devine elementul superior într-un O (1) timpul de funcționare. Vă rugăm să consultați, de asemenea, un exemplu complet în comentariile de cod pentru deserializing. Sper că va ajuta pe cineva lupta mai puțin decât am făcut-o :) Timpul total de funcționare pentru fiecare metodă (serializarea și deserializati) este în același timp de funcționare pentru parcurgeri arbore binar, adică, O (n), unde n este numărul de noduri (intrări) în copac

import java.util.LinkedList; import java.util.List;

public class 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();


}

}

Publicat 21/12/2017 la 16:43
sursa de către utilizator

voturi
-1

Aici este un alt mod de serializarea arbore binar folosind nivelul (modificat) ordine traversal. [Doar copiați și inserați, funcționează] acoperă toate, arbore dezechilibrat, echilibrat, dreapta la stânga oblică oblică.

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
Publicat 28/11/2018 la 00:14
sursa de către utilizator

voturi
0

Aici este un răspuns târziu în Python. Se folosește (adâncime mai întâi) precomandă serializarea și returnează o listă strings. Deserializarea se întoarce copac.

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

A testa:

tree1 = Node('root', Node('left'), Node('right'))
t = deserialize(serialize(tree1))
print(str(t.right.val))
Publicat 28/02/2019 la 02:19
sursa de către utilizator

voturi
-1

Serializarea este procesul de conversie a unei structuri de date sau a unui obiect într-o secvență de biți, astfel încât să poată fi stocate într-un fișier sau tampon de memorie, sau transmise printr-o legătură conexiune de rețea pentru a fi reconstruit mai târziu, în același sau un alt mediu de calculator.

Deserializarea este procesul de conversie șir înapoi la structura copac originală.

Conceptul de serializarea si deserializarea este foarte similar cu ceea ce un compilator nu pentru cod. Există mai multe faze în întregul proces de compilare, dar vom încerca să-l păstrați abstracte.

Având în vedere o bucată de cod, compilator rupe diferite componente bine definite în jetoane (de exemplu, int este un simbol, dublu este un alt simbol, {este un jeton,} este un alt simbol, etc). [Link la o demonstrație a nivelului abstract de compilare] [1].

Serializare: Noi folosim logica parcurgeri precomandă pentru serializarea copac la un șir. Vom adăuga „X“ pentru a desemna un nul pointer / nod într-un copac. În plus, pentru a păstra logica noastră deserializarea în minte, trebuie să adăugați „“ după fiecare valoare nod serializate, astfel încât procesul de deserializarea poate avea acces la fiecare valoare de nod split cu „“.

Link Leetcode: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/

Explicație prin spate în spate SWE Youtube canal : 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));
Publicat 16/07/2019 la 22:52
sursa de către utilizator

voturi
0

Eu nu sunt folosind precomandă dar eu sunt , folosind BFS. Aceasta este o întrebare de la leetcode

Majoritatea oamenilor de punere în aplicare sunt incorecte atunci când se utilizează precomandă: rezultatul așteptat ar trebui să fie

"[1,2,3, null, null, 4,5]", dar în schimb oamenii majoritare de imprimare de ieșire ca "[1,2,3, nul, nul, 4,5, null, null]", deoarece acestea sunt nu de numărare nivelurile.

Aici este punerea în aplicare a mea cu rezultatul corect.

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)
Publicat 09/10/2019 la 02:02
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more