forked from rishabhgarg25699/Competitive-Programming
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SerializeDeserialize.java
222 lines (183 loc) · 7.23 KB
/
SerializeDeserialize.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/**
* Java program to serialize a binary tree, i.e. convert it
* into a serial object, e.g. a string, and deserialize to a
* binary tree, i.e. convert a serial object, e.g. a string
* to a binary tree
*
* (Assumption: Binary Tree is of unique Character nodes)
*
* (Serialization) Algorithm:
* Find the Inorder traversal of the tree
* Find the Preorder traversal of the tree
* Concatenate the results
*
* Time Complexity: O(n) {n is number of nodes}
* Extra Space Complexity: O(h) {h is height of tree}
*
* (Deserialization) Algorithm:
* Separate out the Inorder and Preorder traversals
* For each entry, let c, in the Preorder traversal
* Create a Node for c
* Fetch the left and right substrings of c in the
* Inorder traversal
* Recur for the left and right substrings subse-
* quently passed as Inorder traversal for the
* current node's lower subtree
*
* Time Complexity: O(n^2) {n is number of nodes}
* Extra Space Complexity: O(h) {h is height of tree}
*
* Example:
* Inorder: GDHBEACIF
* Preorder: ABDGHECFI
*
* GDHBE[A]CIF
* / \
* GDH[B]E [C]IF
* / \ \
* G[D]H [E] I[F]
* / \ /
* [G] [H] [I]
*/
class SerializeDeserialize {
public static void main(String args[]) {
// creating and printing the Inorder and Preorder traversals of
// an example Binary Character Tree with unique characters
CharacterTree tree = new CharacterTree();
tree.makeExample();
System.out.println("Example Tree\n------------");
System.out.println("Inorder : " + CharacterTree.inorderTraverse(tree.root));
System.out.println("Preorder: " + CharacterTree.preorderTraverse(tree.root));
// creating and printing the serial form of the tree
String s = serializeTree(tree);
System.out.println("\n" + "Serialized Tree: " + s + "\n");
// creating and printing the Inorder and Preorder traversals of
// the deserialized tree
CharacterTree dest = deserializeTree(s);
System.out.println("Deserialized Tree\n-----------------");
System.out.println("Inorder : " + CharacterTree.inorderTraverse(dest.root));
System.out.println("Preorder: " + CharacterTree.preorderTraverse(dest.root));
// (the traversals of the original and deserialized trees match)
}
// ------ Serialization ------
// method to get the Tree in Serial form (here a String)
static String serializeTree(CharacterTree tree) {
StringBuilder s = new StringBuilder("");
s.append(tree.getInorder());
s.append(tree.getPreorder());
return new String(s);
}
// ------ Deserialization ------
static int pos;
// method to get the deserialized tree from Serial form (here a String)
static CharacterTree deserializeTree(String s) {
CharacterTree tree = new CharacterTree();
String inorder = s.substring(0, s.length() >> 1); // 1st half of string
String preorder = s.substring(s.length() >> 1); // 2nd half of string
// static variable 'pos' indicates the next element in the
// preorder string that is to be converted to a node
pos = 0; // initializing the static varible
// calling the overloaded utility recursive function that
// actually generates the deserialized tree
tree.root = deserializeTree(inorder, preorder);
return tree;
}
// overloaded utility method to generate the deserialized tree
static CharacterTree.Node deserializeTree(String inorder, String preorder) {
// base case
if (inorder.length() == 0) return null;
// identifying the next character in preorder string
char c = preorder.charAt(pos++);
// creating the node for the character
CharacterTree.Node temp = new CharacterTree.Node(c);
// recurring the subtree generation for the left substring
// of 'c' in 'inorder' in the current instance of this method
// in the method call stack
temp.left = deserializeTree(
inorder.substring(0, inorder.indexOf(c)), preorder
);
// recurring the subtree generation for the right substring
// of 'c' in 'inorder' in the current instance of this method
// in the method call stack
temp.right = deserializeTree(
inorder.substring(inorder.indexOf(c) + 1), preorder
);
// retuning the newly created node as root of subtree generated
// from this node, in the deserialized tree
return temp;
}
}
// defining a custom Character Tree ADT
class CharacterTree {
// defining a Tree node
static class Node {
char value;
Node left, right;
// constructor
Node(char value) {
this.value = value;
left = right = null;
}
}
// points to the root node of the tree
Node root = null;
// returns Inorder traversal of the current Tree object
String getInorder() {
return inorderTraverse(root);
}
// returns Preorder traversal of the current Tree object
String getPreorder() {
return preorderTraverse(root);
}
// generates the Inorder traversal of a Tree considering
// the passed node as root
static String inorderTraverse(Node root) {
StringBuilder s = new StringBuilder("");
// calls the overloaded utility function
inorderTraverse(root, s);
return new String(s);
}
// overloaded recurring method to generate the Inorder
// traversal of the subtree considering 'root' as root
static void inorderTraverse(Node root, StringBuilder s) {
if (root == null) return;
inorderTraverse(root.left, s);
s.append(root.value);
inorderTraverse(root.right, s);
}
// generates the Preorder traversal of a Tree considering
// the passed node as root
static String preorderTraverse(Node root) {
StringBuilder s = new StringBuilder("");
// calls the overloaded utility function
preorderTraverse(root, s);
return new String(s);
}
// overloaded recurring method to generate the Preorder
// traversal of the subtree considering 'root' as root
static void preorderTraverse(Node root, StringBuilder s) {
if (root == null) return;
s.append(root.value);
preorderTraverse(root.left, s);
preorderTraverse(root.right, s);
}
// makes an example Character Tree with unique characters
void makeExample() {
root = new Node('A');
root.left = new Node('B');
root.left.left = new Node('D');
root.left.left.left = new Node('G');
root.left.left.right = new Node('H');
root.left.right = new Node('E');
root.right = new Node('C');
root.right.right = new Node('F');
root.right.right.left = new Node('I');
// (Tree) A
// / \
// B C
// / \ \
// D E F
// / \ /
// G H I
}
}