Elmentem egy interjút, ahol ma megkértek, hogy sorosításához bináris fa. I végre egy tömb-alapú megközelítés, ahol a gyerekek i csomópont (számozás szint-sorrendben bejárás) voltak a 2 * i index a bal gyermek, és 2 * i + 1 a jobb fia. A kérdező tűnt többé-kevésbé elégedett, de kíváncsi vagyok, hogy mit jelent pontosan serialize? Vajon kifejezetten vonatkoznak összeolvasztás a fa lemezre írásnál, vagy pedig szerializálásáról egy fa is tartalmazhat csak fordult a fa egy láncolt lista, mondjuk. Továbbá, hogyan érjük el egyengető a fa egy (kétszeresen) láncolt lista, majd rekonstruálva? Tud újra a pontos szerkezete a fa a láncolt lista?
Hogyan sorosításához bináris fa
1. megközelítés: Nem mind Inorder és Előrendelési bejárás a searialize a fa adatokat. A de-sorszámozás használatra előrendelés do BST Inorder megfelelő módon kialakítani a fát.
Be kell egyrészt azért, mert -> A B -> C jelölhető előrendelhető bár a szerkezet különböző lehet.
2. megközelítés: A #, mint egy őrszem Bárhol a bal vagy a jobb gyermek null .....
Mit szólnál működés közbeni érdekében bejárás és véget a gyökér kulcs, és minden csomópont kulcsokat egy std :: listából vagy más tartály választott, amely kisimítja a fát. Ezután egyszerűen szerializálni az std :: listából vagy konténer választott a boost könyvtárban.
A fordított egyszerű, majd újjáépíteni a fa standard beillesztési egy bináris fa. Ez nem lehet teljesen hatékony egy nagyon nagy fa, de futás közben átalakítani a fa egy std :: lista O (n) legfeljebb, és újjáépíteni a fa O (log n) a legtöbb.
Én körülbelül ezt sorosításához egy fa csak kódolt fel c ++, mint én konvertálása adatbázis Java C ++.
Mindazok cikkek beszélni többnyire a sorszámozás részét. A deserialization része kissé trükkös csinálni egy menetben.
Azt már végre egy hatékony megoldás deserialization is.
Probléma: sorosításához és deserialize egy bináris fa, amely a pozitív számok.
Sorszámozás rész:
- 0 használatával képviseli null.
- Sorosításához felsorolni az egész számok segítségével előrendelésre bejárás.
Deserialization rész:
- Tudomásul listán egészek, és használja rekurzív segítő módszert deserialization.
- Rekurzív deserializer vissza egy pár (BTNode csomópont, int nextIndexToRead) adott csomópont csomópontja épített eddig, és nextIndexToRead jelentése helyzete a következő számot kell olvasni a szerializált számok listája.
Az alábbiakban a kód 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;
}
}
A legjobb módja az, hogy egy speciális karakter (mint #, mint a korábbi megjegyzést említik), mint őrszem. Ez jobb, mint szerkesztünk egy inorder bejárása tömb és egy előrendelésre / postorder bejárás tömb, mind térben bonyolultsága bölcs és időbonyolultsága bölcs. ez is módja könnyebben megvalósítható.
A csatolt felsorolás nem jó illeszkedést óta itt annak érdekében, hogy rekonstruálják a fa, jobb, ha van const elem elérési idő
Az előre érdekében bejárás szerializálni bináris fa. Használja ugyanazt a pre érdekében bejárás a deserialize fa. Légy óvatos a szélső esetek. Itt null csomópontok által képviselt „#”
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;
}
Már próbál a lényeget. Tehát itt van a Java megvalósítása. Mint említettük, ez egy bináris fa nem BST. Mert szerializálásáról, előrendelésre vásárolható bejárás tűnik, hogy működik egyszerűbb (egy string „NULL” for null csomópontok). Kérjük, ellenőrizze az alábbi kódot egy teljes példa rekurzív hívások. A deserializing, a húr alakítjuk át láncolt lista, ahol eltávolítás (0) kap a felső eleme egy O (1) futási ideje. Kérjük, olvassa el a teljes például a megjegyzéseket a kódot deserializing. Remélem, hogy segít valaki küzd kisebb, mint én :) A teljes működési ideje minden módszer (sorosításához és deserialize) ugyanaz működési ideje bináris fa bejárás, tehát O (n), ahol n a csomópontok száma (bejegyzés) a fában
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();
}
}
Itt van egy másik módja szerializálásáról bináris fa segítségével (módosított) komissiózó bejárás. [Csak másold be, akkor működik] Tartalmazza az összes kiegyensúlyozatlan, kiegyensúlyozott, jobbra ferde, balra ferde fa.
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
Itt van egy késői válasz Python. Ez használ (mélységi) előrendelésre sorozatprogramozásának listáját adja vissza strings. Deserialization visszaadja a fa.
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
Tesztelni:
tree1 = Node('root', Node('left'), Node('right'))
t = deserialize(serialize(tree1))
print(str(t.right.val))
Sorszámozás a folyamat, amely egy adatszerkezetet vagy tárgy egy bitsorozatot úgy, hogy lehet tárolni egy fájl vagy memória puffer, vagy továbbított hálózati kapcsolaton keresztül a linket rekonstruálható később ugyanazon vagy egy másik számítógépes környezetben.
Deserialization az a folyamat átalakítása a húr vissza az eredeti fa szerkezet.
Fogalma sorozatprogramozásának deserialization nagyon hasonlít ahhoz, amit a fordítóprogramnak kódolni. Vannak több fázisban az egész fordítási folyamatot, de megpróbáljuk tartani elvont.
Adott egy darab kód, fordító megtöri különböző jól definiált komponensek jelzőt (például int egy jelképes, kettős egy másik token, {egy token,} egy másik token, stb). [Link bemutatót az absztrakt szintű összeállítás] [1].
Sorszámozás: használjuk előrendelésre bejárás logikája szerializálásáról fa egy string. Mi lesz hozzá "X" jelöli a null pointer / node egy fa. Ezen kívül, hogy megtartsuk a deserialization logikát követve, mi kell hozzá „” miután minden sorozatban csomópont értékét úgy, hogy a folyamat deserialization elérheti minden csomópont értéke split „”.
Leetcode Link: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
Magyarázat a háttal SWE Youtube csatorna : 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));
Én nem használ előrendelhető, de én vagyok a BFS. Ez egy kérdés leetcode
Az emberek többsége végrehajtás helytelen használata előrendelhető: a várt eredményt kell
"[1,2,3, null, null, 4,5]", hanem többségi emberek kinyomtatni a kimenetet "[1,2,3, null, null, 4,5, null, null]", mivel ők nem számítva a szinteket.
Itt van a végrehajtás a helyes eredményt.
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)













