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
463e2b61
Commit
463e2b61
authored
Feb 14, 2022
by
David Mareček
Browse files
new term cleanup
parent
396696d8
Changes
87
Hide whitespace changes
Inline
Side-by-side
01-tree_successor/cpp/Makefile
deleted
100644 → 0
View file @
396696d8
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
deleted
100644 → 0
View file @
396696d8
#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
deleted
100644 → 0
View file @
396696d8
// 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
deleted
100644 → 0
View file @
396696d8
#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
deleted
100644 → 0
View file @
396696d8
#!/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
deleted
100644 → 0
View file @
396696d8
#!/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
deleted
100644 → 0
View file @
396696d8
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.*`
).
02-splay_operation/cpp/Makefile
deleted
100644 → 0
View file @
396696d8
test
:
splay_operation_test
./
$<
CXXFLAGS
=
-std
=
c++11
-O2
-Wall
-Wextra
-g
-Wno-sign-compare
splay_operation_test
:
splay_operation.h splay_operation_test.cpp test_main.cpp
$(CXX)
$(CXXFLAGS)
$^
-o
$@
clean
::
rm
-f
splay_operation_test
.PHONY
:
clean test
02-splay_operation/cpp/splay_operation.h
deleted
100644 → 0
View file @
396696d8
// A node of the tree
class
Node
{
public:
int
key
;
Node
*
left
;
Node
*
right
;
Node
*
parent
;
// Constructor
Node
(
int
key
,
Node
*
parent
=
nullptr
,
Node
*
left
=
nullptr
,
Node
*
right
=
nullptr
)
{
this
->
key
=
key
;
this
->
parent
=
parent
;
this
->
left
=
left
;
this
->
right
=
right
;
if
(
left
)
left
->
parent
=
this
;
if
(
right
)
right
->
parent
=
this
;
}
};
// Binary tree
class
Tree
{
public:
// Pointer to root of the tree; nullptr if the tree is empty.
Node
*
root
;
Tree
(
Node
*
root
=
nullptr
)
{
this
->
root
=
root
;
}
// Rotate the given `node` up. Perform a single rotation of the edge
// between the node and its parent, choosing left or right rotation
// appropriately.
virtual
void
rotate
(
Node
*
node
)
{
if
(
node
->
parent
)
{
if
(
node
->
parent
->
left
==
node
)
{
if
(
node
->
right
)
node
->
right
->
parent
=
node
->
parent
;
node
->
parent
->
left
=
node
->
right
;
node
->
right
=
node
->
parent
;
}
else
{
if
(
node
->
left
)
node
->
left
->
parent
=
node
->
parent
;
node
->
parent
->
right
=
node
->
left
;
node
->
left
=
node
->
parent
;
}
if
(
node
->
parent
->
parent
)
{
if
(
node
->
parent
->
parent
->
left
==
node
->
parent
)
node
->
parent
->
parent
->
left
=
node
;
else
node
->
parent
->
parent
->
right
=
node
;
}
else
{
root
=
node
;
}
Node
*
original_parent
=
node
->
parent
;
node
->
parent
=
node
->
parent
->
parent
;
original_parent
->
parent
=
node
;
}
}
// Look up the given key in the tree, returning the
// the node with the requested key or nullptr.
Node
*
lookup
(
int
key
)
{
// TODO: Utilize splay suitably.
Node
*
node
=
root
;
while
(
node
)
{
if
(
node
->
key
==
key
)
{
return
node
;
}
if
(
key
<
node
->
key
)
node
=
node
->
left
;
else
node
=
node
->
right
;
}
return
nullptr
;
}
// Insert a key into the tree.
// If the key is already present, nothing happens.
void
insert
(
int
key
)
{
// TODO: Utilize splay suitably.
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
;
}
}
}
// Delete given key from the tree.
// It the key is not present, nothing happens.
void
remove
(
int
key
)
{
// TODO: Utilize splay suitably.
Node
*
node
=
root
;
while
(
node
&&
node
->
key
!=
key
)
{
if
(
key
<
node
->
key
)
node
=
node
->
left
;
else
node
=
node
->
right
;
}
if
(
node
)
{
if
(
node
->
left
&&
node
->
right
)
{
Node
*
replacement
=
node
->
right
;
while
(
replacement
->
left
)
replacement
=
replacement
->
left
;
node
->
key
=
replacement
->
key
;
node
=
replacement
;
}
Node
*
replacement
=
node
->
left
?
node
->
left
:
node
->
right
;
if
(
node
->
parent
)
{
if
(
node
->
parent
->
left
==
node
)
node
->
parent
->
left
=
replacement
;
else
node
->
parent
->
right
=
replacement
;
}
else
{
root
=
replacement
;
}
if
(
replacement
)
replacement
->
parent
=
node
->
parent
;
delete
node
;
}
}
// Splay the given node.
// If a single rotation needs to be performed, perform it as the last rotation
// (i.e., to move the splayed node to the root of the tree).
virtual
void
splay
(
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
;
}
}
};
02-splay_operation/cpp/splay_operation_test.cpp
deleted
100644 → 0
View file @
396696d8
#include <algorithm>
#include <cassert>
#include <fstream>
#include <functional>
#include <string>
#include <utility>
#include <vector>
#include "splay_operation.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
);
// Flatten the tree: return a sorted list of all keys in the tree.
vector
<
int
>
flatten
(
const
Tree
&
tree
)
{
constexpr
int
L
=
0
,
R
=
1
,
F
=
2
;
Node
*
node
=
tree
.
root
;
vector
<
int
>
flattened
,
stack
=
{
L
};
while
(
!
stack
.
empty
())
{
if
(
stack
.
back
()
==
L
)
{
stack
.
back
()
=
R
;
if
(
node
->
left
)
{
node
=
node
->
left
;
stack
.
push_back
(
L
);
}
}
else
if
(
stack
.
back
()
==
R
)
{
flattened
.
push_back
(
node
->
key
);
stack
.
back
()
=
F
;
if
(
node
->
right
)
{
node
=
node
->
right
;
stack
.
push_back
(
L
);
}
}
else
{
node
=
node
->
parent
;
stack
.
pop_back
();
}
}
return
flattened
;
}
// Test for splay operation with required helpers
class
TestSplay
{
public:
static
Node
*
deserialize_node
(
const
string
&
text
,
int
&
index
)
{
EXPECT
(
text
[
index
++
]
==
'('
,
"Internal error during example deserialization"
);
if
(
text
[
index
]
==
')'
)
{
index
++
;
return
nullptr
;
}
else
{
int
comma
=
text
.
find
(
','
,
index
);
int
key
=
stoi
(
text
.
substr
(
index
,
comma
-
index
));
Node
*
left
=
deserialize_node
(
text
,
(
index
=
comma
+
1
));
Node
*
right
=
deserialize_node
(
text
,
++
index
);
EXPECT
(
text
[
index
++
]
==
')'
,
"Internal error during example deserialization"
);
return
new
Node
(
key
,
nullptr
,
left
,
right
);
}
}
static
Node
*
deserialize_root
(
const
string
&
text
)
{
int
index
=
0
;
Node
*
root
=
deserialize_node
(
text
,
index
);
assert
(
index
==
text
.
size
());
return
root
;
}
static
string
compare
(
Node
*
system
,
Node
*
gold
)
{
if
(
!
system
&&
gold
)
{
return
"expected node with key "
+
to_string
(
gold
->
key
)
+
", found None"
;
}
else
if
(
system
&&
!
gold
)
{
return
"expected None, found node with key "
+
to_string
(
system
->
key
);
}
else
if
(
system
&&
gold
)
{
if
(
system
->
key
!=
gold
->
key
)
return
"expected node with key "
+
to_string
(
gold
->
key
)
+
", found "
+
to_string
(
system
->
key
);
auto
result
=
compare
(
system
->
left
,
gold
->
left
);
if
(
!
result
.
empty
())
return
result
;
return
compare
(
system
->
right
,
gold
->
right
);
}
return
string
();
}
static
void
test
()
{
ifstream
splay_tests_file
(
"splay_tests.txt"
);
EXPECT
(
splay_tests_file
.
is_open
(),
"Cannot open splay_tests.txt file with the tests"
);
string
original
,
splayed
;
int
target
;
while
(
splay_tests_file
>>
original
>>
target
>>
splayed
)
{
Tree
original_tree
(
deserialize_root
(
original
));
Tree
splayed_tree
(
deserialize_root
(
splayed
));
Node
*
target_node
=
original_tree
.
root
;
while
(
target_node
&&
target_node
->
key
!=
target
)
if
(
target
<
target_node
->
key
)
target_node
=
target_node
->
left
;
else
target_node
=
target_node
->
right
;
EXPECT
(
target_node
,
"Internal error during finding the target node in the tree to splay"
);
original_tree
.
splay
(
target_node
);
auto
error
=
compare
(
original_tree
.
root
,
splayed_tree
.
root
);
EXPECT
(
error
.
empty
(),
"Error running splay on key "
+
to_string
(
target
)
+
" of "
+
original
+
": "
+
error
);
}
}
};
void
test_lookup
()
{
// Insert even numbers
Tree
tree
;
for
(
int
i
=
0
;
i
<
5000000
;
i
+=
2
)
tree
.
insert
(
i
);
// Find non-existing
for
(
int
i
=
1
;
i
<
5000000
;
i
+=
2
)
for
(
int
j
=
0
;
j
<
10
;
j
++
)
EXPECT
(
!
tree
.
lookup
(
i
),
"Non-existing element was found"
);
// Find existing
for
(
int
i
=
0
;
i
<
5000000
;
i
+=
2
)
for
(
int
j
=
0
;
j
<
10
;
j
++
)
EXPECT
(
tree
.
lookup
(
i
),
"Existing element was not found"
);
}
void
test_insert
()
{
// Test validity first
{
Tree
tree
;
vector
<
int
>
sequence
=
{
997
};
for
(
int
i
=
2
;
i
<
1999
;
i
++
)
sequence
.
push_back
((
sequence
.
back
()
*
sequence
.
front
())
%
1999
);
for
(
const
auto
&
i
:
sequence
)
tree
.
insert
(
i
);
vector
<
int
>
flattened
=
flatten
(
tree
);
sort
(
sequence
.
begin
(),
sequence
.
end
());