-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
428 lines (382 loc) · 12.6 KB
/
main.cpp
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
//
// Project 4
// Created by Gabe Scott on 2019-03-27.
//
#include <iostream>
using namespace std;
class Tree
{
friend void operator<< (ostream& s, Tree& t); //prints parent array
protected:
int* parentArray;
int size;
int root;
public:
Tree(); // Default Constructor
Tree(int numNodes); // Non-Default const
Tree(Tree& data); // copy const
~Tree(); // destructor
void LCA(int a, int b); // Least common Ancestor
int Parent(int node); // Get the parents of node i
void Children(int node); // Prints as well as returns an array.
int* ChildrenArray(int node); // Same as Children() but returns an array instead of prints
void Siblings(int node); // get the siblings of node i
void Root(); // get the root of the tree
void setRoot(int rootNode);
void setParent(int node, int parent);
void nodesAtLevel(int level); // give the nodes at level i
void Level(int node); // print the level of node i
int returnLevel(int node); // same as Level() but returns an int instead of void. I use this is LCA().
void height(); // print the height of the tree
void Preorder(); // give the preorder traversal of the tree
void Preorder(int node);
};
Tree::Tree() // default constructor
{
parentArray = new int[0];
size = 0;
root = -1;
}
Tree::Tree(int numNodes) // Non default constructor
{
parentArray = new int[numNodes];
size = numNodes;
}
Tree::Tree(Tree& data) // Copy constructor
{
parentArray = new int[data.size];
size = data.size;
root = data.root;
// iterate through parentArray and copy each element over
for (int i=0; i<data.size; i++)
{
parentArray[i] = data.parentArray[i];
}
}
Tree::~Tree() // destructor
{
if (parentArray != NULL)
delete[] parentArray;
parentArray = NULL;
size = 0;
//root = NULL;
}
int Tree::Parent(int node) // returns the parent of a given node
{
return parentArray[node];
}
void Tree::Children(int node) // Method prints children of a given node.
{
for (int i=0; i<size; i++)
{
if (parentArray[i] == node)
{
cout << i << " ";
}
}
cout << endl;
}
int* Tree::ChildrenArray(int node) //Method is same as Children() except that it returns an array and doesn't print
{
// create an array of children that will have -1 if not a child and a different value if a valid child
int* childrenArray = new int[size];
for (int i=0; i < size; i++)
{
childrenArray[i] = -1;
}
// iterate through parent array and if it matches the input node, input it into the childrenArray
for (int i=0; i<size; i++)
{
if (parentArray[i] == node)
{
childrenArray[i] = i;
}
}
return childrenArray;
}
void Tree::Siblings(int node) // prints the nodes at same level as input node
{
int parent = Parent(node);
for (int i=0; i<size; i++)
{
if (Parent(i) == parent && i != node)
{
cout << i << " ";
}
}
cout << endl;
}
void Tree::Root() // returns Root of the tree
{
for (int i=0; i<size; i++)
{
if (parentArray[i] == -1)
{
cout << i;
}
}
cout << endl;
}
void Tree::nodesAtLevel(int level) // Prints all nodes at any given level
{
// create Array containing level of each Node
int* nodeLevels = new int[size];
// iterate through parentArray and get level of each node
int lvlCounter= 0;
int currNode = 0;
for (int i=0; i<size; i++)
{
// start at node i in array
currNode = i;
// go through parent array from one node to the next, with the next being its parent. Stop when current node is -1 because we're at the root of the tree
lvlCounter = 0; // starting at 0 b/c it will add an extra count on the step from the root to -1
while (currNode != -1)
{
currNode = parentArray[currNode];
lvlCounter++;
// the counter will be the level for the node we started on
}
// add level to Array containing the level of each node
nodeLevels[i] = lvlCounter;
}
// now iterate through nodeLevels array and cout the nodes that have level of input
for (int i=0; i<size; i++)
{
if (nodeLevels[i] == level)
{
cout << i << " ";
}
}
cout << endl;
}
void Tree::Level(int node) // Gives level of input node
{
// create Array containing level of each Node
int* nodeLevels = new int[size];
// iterate through parentArray and get level of each node
int lvlCounter= 0;
int currNode = 0;
for (int i=0; i<size; i++)
{
// start at node i in array
currNode = i;
// go through parent array from one node to the next, with the next being its parent. Stop when current node is -1 because we're at the root of the tree
lvlCounter = 0; // starting at 0 b/c it will add an extra count on the step from the root to -1
while (currNode != -1)
{
currNode = parentArray[currNode];
lvlCounter++;
// the counter will be the level for the node we started on
}
// add level to Array containing the level of each node
nodeLevels[i] = lvlCounter;
}
cout << nodeLevels[node] << endl;
}
int Tree::returnLevel(int node) // This method is same as Level() but returns an int instead of void/cout. For use with method LCA()
{
// create Array containing level of each Node
int* nodeLevels = new int[size];
// iterate through parentArray and get level of each node
int lvlCounter= 0;
int currNode = 0;
for (int i=0; i<size; i++)
{
// start at node i in array
currNode = i;
// go through parent array from one node to the next, with the next being its parent. Stop when current node is -1 because we're at the root of the tree
lvlCounter = 0; // starting at 0 b/c it will add an extra count on the step from the root to -1
while (currNode != -1)
{
currNode = parentArray[currNode];
lvlCounter++;
// the counter will be the level for the node we started on
}
// add level to Array containing the level of each node
nodeLevels[i] = lvlCounter;
}
return nodeLevels[node];
}
// Prints height of the tree by creating an array that contains the level for each node. Then prints the highest of those levels.
void Tree::height()
{
// create Array containing level of each Node
int* nodeLevels = new int[size];
// iterate through parentArray and get level of each node
int lvlCounter= 0;
int currNode = 0;
for (int i=0; i<size; i++)
{
// start at node i in array
currNode = i;
// go through parent array from one node to the next, with the next being its parent. Stop when current node is -1 because we're at the root of the tree
lvlCounter = 0; // starting at 0 b/c it will add an extra count on the step from the root to -1
while (currNode != -1)
{
currNode = parentArray[currNode];
lvlCounter++;
// the counter will be the level for the node we started on
}
// add level to Array containing the level of each node
nodeLevels[i] = lvlCounter;
}
// Now go through nodeLevels array and find the maximum level. This will be the height of the tree.
int maxLevel = 0;
for (int i = 0; i<size; i++)
{
if (nodeLevels[i] > maxLevel)
{
maxLevel = nodeLevels[i];
}
}
cout << maxLevel << endl;
}
void Tree::LCA(int a, int b) // prints the least common ancestor of the two input nodes
{
//if A == B print parent
if (a == b)
{
cout << Parent(a) << endl;;
return;
}
// lowest will be node with the highest level, or equal to highest level. (Lowest as in lower on the tree when looking at it)
int lowest;
int highest;
if (returnLevel(a) >= returnLevel(b))
{
lowest = a;
highest = b;
}
else
{
lowest = b;
highest = a;
}
int ancestor = -1;
// setting two new variables to lowest and highest so we can manipulate them without losing original lowest and highest
int currLow = lowest;
int currHigh = highest;
// this will loop the number of times of the level of the highest of the two nodes
for (int i=0; i<(returnLevel(highest)); i++)
{
// this will loop the number of times of the level of the lowest of the two nodes
for (int j=0; j< ((returnLevel(lowest))); j++)
{
// resetting lowest on first iteration of for loop each time
if (j == 0)
currLow = lowest;
// move currLow up the chain to its parent
currLow = Parent(currLow);
// if currLow matches currHigh, we've found our ancestor. set and break out of loop.
if (currLow == currHigh)
{
ancestor = currLow;
break;
}
}
// if ancestor isn't -1, we already have it, break loop.
if (ancestor != -1)
break;
else
{
// otherwise, move currHigh up the chain to its parent
currHigh = Parent(currHigh);
}
}
cout << ancestor << endl;
}
void operator<< (ostream& s, Tree& t) // Overloaded ostream operator
{
for (int i=0; i<t.size; i++)
{
cout << i << ": " << t.parentArray[i] << " ";
}
cout << endl;
}
void Tree::setParent(int node, int parent)
{
parentArray[node] = parent;
}
void Tree::setRoot(int rootNode)
{
root = rootNode;
parentArray[rootNode] = -1;
}
void Tree::Preorder() //Preoder recursion. Prints root then Calls Preorder(node) on the root
{
cout << root << " ";
Preorder(root);
}
void Tree::Preorder(int node) // Recursive function that prints nodes in preoder fashion
{
//calls ChildrenArray on input node, then prints input node, then calls itself on that node
int* childArray = ChildrenArray(node);
for (int i=0; i<this->size; i++)
{
// if childArray value is not -1, print it then call this function again on that node
if (childArray[i] != -1)
{
cout << childArray[i] << " ";
Preorder(childArray[i]);
}
}
}
int main()
{
Tree* myTree;
int numNodes, node, parent;
cin >> numNodes;
myTree = new Tree(numNodes);
for (int i=0; i<numNodes; i++)
{
cin >> node >> parent;
(*myTree).setParent(node, parent);
if (parent == -1)
{
(*myTree).setRoot(node);
}
}
cout << "The tree that we just read is:" << endl;
cout << *myTree;
cout << endl;
Tree* newTree = new Tree(*myTree);
cout << "The tree that we just copied is: " << endl;
cout << *newTree;
cout << endl;
cout << "The root of the tree is: ";
(*myTree).Root();
cout << endl;
cout << "The least common ancestor of nodes 3 and 8 is: ";
(*myTree).LCA(3,8);
cout << endl;
cout << "The least common ancestor of nodes 13 and 8 is: ";
(*myTree).LCA(13,8);
cout << endl;
cout << "The least common ancestor of nodes 13 and 11 is: ";
(*myTree).LCA(13,11);
cout << endl;
cout << "The children of node 12 is/are: " << endl;
(*myTree).Children (12);
cout << "The children of node 10 is/are: " << endl;
(*myTree).Children (10);
cout << "The siblings of node 3 is/are: " << endl;
(*myTree).Siblings (3);
cout << "The siblings of node 12 is/are: " << endl;
(*myTree).Siblings (12);
cout << "The nodes at level 3 is/are: " << endl;
(*myTree).nodesAtLevel (3);
cout << "The height of the tree is: " ;
(*myTree).height();
cout << endl;
cout << "The level of node 3 in the tree is: " ;
(*myTree).Level(3);
cout<< endl;
cout << "The level of node 12 in the tree is: ";
(*myTree).Level(12);
cout << endl;
cout << "The preorder traversal of the tree is/are: " << endl;
(*myTree).Preorder();
cout << endl;
delete myTree;
delete newTree;
}