Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
datovky
assignments
Commits
0f460c7f
Commit
0f460c7f
authored
Sep 30, 2021
by
Ondřej Mička
Browse files
Tree successor
parent
4ce16bf0
Changes
7
Hide whitespace changes
Inline
Side-by-side
01-tree_successor/cpp/Makefile
0 → 100644
View file @
0f460c7f
test
:
tree_successor_test
./
$<
CXXFLAGS
=
-std
=
c++11
-O2
-Wall
-Wextra
-g
-Wno-sign-compare
tree_successor_test
:
tree_successor.h tree_successor_test.cpp test_main.cpp
$(CXX)
$(CXXFLAGS)
$^
-o
$@
clean
:
rm
-f
tree_successor_test
.PHONY
:
clean test
01-tree_successor/cpp/test_main.cpp
0 → 100644
View file @
0f460c7f
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
using
namespace
std
;
extern
vector
<
pair
<
string
,
function
<
void
()
>>>
tests
;
void
expect_failed
(
const
string
&
message
)
{
cerr
<<
"Test error: "
<<
message
<<
endl
;
exit
(
1
);
}
int
main
(
int
argc
,
char
*
argv
[])
{
vector
<
string
>
required_tests
;
if
(
argc
>
1
)
{
required_tests
.
assign
(
argv
+
1
,
argv
+
argc
);
}
else
{
for
(
const
auto
&
test
:
tests
)
required_tests
.
push_back
(
test
.
first
);
}
for
(
const
auto
&
required_test
:
required_tests
)
{
bool
found
=
false
;
for
(
const
auto
&
test
:
tests
)
if
(
required_test
==
test
.
first
)
{
cerr
<<
"Running test "
<<
required_test
<<
endl
;
test
.
second
();
found
=
true
;
break
;
}
if
(
!
found
)
{
cerr
<<
"Unknown test "
<<
required_test
<<
endl
;
return
1
;
}
}
return
0
;
}
01-tree_successor/cpp/tree_successor.h
0 → 100644
View file @
0f460c7f
// A node of the tree
class
Node
{
public:
int
key
;
Node
*
left
;
Node
*
right
;
Node
*
parent
;
// Constructor
Node
(
int
key
,
Node
*
parent
=
nullptr
)
{
this
->
key
=
key
;
this
->
parent
=
parent
;
this
->
left
=
nullptr
;
this
->
right
=
nullptr
;
}
};
// Binary tree
class
Tree
{
public:
// Pointer to root of the tree; nullptr if the tree is empty.
Node
*
root
=
nullptr
;
// Insert a key into the tree.
// If the key is already present, nothing happens.
void
insert
(
int
key
)
{
if
(
!
root
)
{
root
=
new
Node
(
key
);
return
;
}
Node
*
node
=
root
;
while
(
node
->
key
!=
key
)
{
if
(
key
<
node
->
key
)
{
if
(
!
node
->
left
)
node
->
left
=
new
Node
(
key
,
node
);
node
=
node
->
left
;
}
else
{
if
(
!
node
->
right
)
node
->
right
=
new
Node
(
key
,
node
);
node
=
node
->
right
;
}
}
}
// Return successor of the given node.
//
// The successor of a node is the node with the next higher key.
// Return nullptr if there is no such node.
// If the argument is nullptr, return the node with the smallest key.
Node
*
successor
(
Node
*
node
)
{
// TODO: Implement
}
// Destructor to free all allocated memory.
~
Tree
()
{
Node
*
node
=
root
;
while
(
node
)
{
Node
*
next
;
if
(
node
->
left
)
{
next
=
node
->
left
;
node
->
left
=
nullptr
;
}
else
if
(
node
->
right
)
{
next
=
node
->
right
;
node
->
right
=
nullptr
;
}
else
{
next
=
node
->
parent
;
delete
node
;
}
node
=
next
;
}
}
};
01-tree_successor/cpp/tree_successor_test.cpp
0 → 100644
View file @
0f460c7f
#include <algorithm>
#include <functional>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "tree_successor.h"
using
namespace
std
;
// If the condition is not true, report an error and halt.
#define EXPECT(condition, message) do { if (!(condition)) expect_failed(message); } while (0)
void
expect_failed
(
const
string
&
message
);
void
test
(
const
vector
<
int
>&
sequence
)
{
Tree
tree
;
for
(
const
auto
&
element
:
sequence
)
tree
.
insert
(
element
);
vector
<
int
>
sorted_sequence
(
sequence
);
sort
(
sorted_sequence
.
begin
(),
sorted_sequence
.
end
());
Node
*
node
=
tree
.
successor
(
nullptr
);
for
(
const
auto
&
element
:
sorted_sequence
)
{
EXPECT
(
node
,
"Expected successor "
+
to_string
(
element
)
+
", got nullptr"
);
EXPECT
(
node
->
key
==
element
,
"Expected successor "
+
to_string
(
element
)
+
", got "
+
to_string
(
node
->
key
));
node
=
tree
.
successor
(
node
);
}
EXPECT
(
!
node
,
"Expected no successor, got "
+
to_string
(
node
->
key
));
}
vector
<
pair
<
string
,
function
<
void
()
>>>
tests
=
{
{
"right_path"
,
[]
{
vector
<
int
>
numbers
;
for
(
int
i
=
0
;
i
<
10000
;
i
++
)
numbers
.
push_back
((
int
)(
7.13
*
i
));
test
(
numbers
);
}
},
{
"left_path"
,
[]
{
vector
<
int
>
numbers
;
for
(
int
i
=
9999
;
i
>=
0
;
i
--
)
numbers
.
push_back
((
int
)(
7.13
*
i
));
test
(
numbers
);
}
},
{
"random_tree"
,
[]
{
vector
<
int
>
numbers
=
{
997
};
for
(
int
i
=
2
;
i
<
199999
;
i
++
)
numbers
.
push_back
((
numbers
.
back
()
*
int64_t
(
997
))
%
199999
);
test
(
numbers
);
}
},
};
01-tree_successor/python/tree_successor.py
0 → 100644
View file @
0f460c7f
#!/usr/bin/env python3
class
Node
:
"""Node in a binary tree `Tree`"""
def
__init__
(
self
,
key
,
left
=
None
,
right
=
None
,
parent
=
None
):
self
.
key
=
key
self
.
left
=
left
self
.
right
=
right
self
.
parent
=
parent
class
Tree
:
"""A simple binary search tree"""
def
__init__
(
self
,
root
=
None
):
self
.
root
=
root
def
insert
(
self
,
key
):
"""Insert key into the tree.
If the key is already present, do nothing.
"""
if
self
.
root
is
None
:
self
.
root
=
Node
(
key
)
return
node
=
self
.
root
while
node
.
key
!=
key
:
if
key
<
node
.
key
:
if
node
.
left
is
None
:
node
.
left
=
Node
(
key
,
parent
=
node
)
node
=
node
.
left
else
:
if
node
.
right
is
None
:
node
.
right
=
Node
(
key
,
parent
=
node
)
node
=
node
.
right
def
successor
(
self
,
node
=
None
):
"""Return successor of the given node.
The successor of a node is the node with the next greater key.
Return None if there is no such node.
If the argument is None, return the node with the smallest key.
"""
# TODO: Implement
raise
NotImplementedError
01-tree_successor/python/tree_successor_test.py
0 → 100644
View file @
0f460c7f
#!/usr/bin/env python3
import
sys
import
tree_successor
def
test_sequence
(
sequence
):
tree
=
tree_successor
.
Tree
()
for
i
in
sequence
:
tree
.
insert
(
i
)
node
=
tree
.
successor
(
None
)
for
element
in
sorted
(
sequence
):
assert
node
is
not
None
,
"Expected successor {}, got None"
.
format
(
element
)
assert
node
.
key
==
element
,
"Expected successor {}, got {}"
.
format
(
element
,
node
.
key
)
node
=
tree
.
successor
(
node
)
assert
node
is
None
,
"Expected no successor, got {}"
.
format
(
node
.
key
)
def
gen_increasing_seq
():
return
[
int
(
7.13
*
i
)
for
i
in
range
(
10000
)]
tests
=
[
(
"right_path"
,
lambda
:
test_sequence
(
gen_increasing_seq
())),
(
"left_path"
,
lambda
:
test_sequence
(
list
(
reversed
(
gen_increasing_seq
())))),
(
"random_tree"
,
lambda
:
test_sequence
([
pow
(
997
,
i
,
199999
)
for
i
in
range
(
1
,
199999
)])),
]
if
__name__
==
"__main__"
:
for
required_test
in
sys
.
argv
[
1
:]
or
[
name
for
name
,
_
in
tests
]:
for
name
,
test
in
tests
:
if
name
==
required_test
:
print
(
"Running test {}"
.
format
(
name
),
file
=
sys
.
stderr
)
test
()
break
else
:
raise
ValueError
(
"Unknown test {}"
.
format
(
name
))
01-tree_successor/task.md
0 → 100644
View file @
0f460c7f
Given an implementation of a simple binary search tree including parent
pointers, implement a
`successor`
method. The methods is given a node
and it should return another node of the tree with the next higher key
(i.e., the smallest of keys which are greater than the given one).
-
If there is no such node, it should return a null pointer.
-
The given node can also be a null pointer, in which case the method should
return the smallest node in the tree.
You can expect that
`successor`
method is never called on an empty tree.
You should submit the file
`tree_successor.*`
(but not the
`tree_successor_test.*`
).
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment