diff --git a/src/classes/tree/avl_tree.h b/src/classes/tree/avl_tree.h index b25062ef..48c5aa4d 100644 --- a/src/classes/tree/avl_tree.h +++ b/src/classes/tree/avl_tree.h @@ -30,6 +30,12 @@ template class avl_tree { */ void insert(T key) { root = __insert(root, key); } + /* + *search function. + *@param key: key to be searched. + */ + bool search(T key) { return __search(root, key); } + /* *remove function. *@param key: key to be removed. @@ -180,6 +186,18 @@ template class avl_tree { } return root; } + bool __search(node *root, T key) { + while (root) { + if (root->info < key) { + root = root->right; + } else if (root->info > key) { + root = root->left; + } else { + return true; + } + } + return false; + } void __inorder(std::function callback, node *root) { if (root) { diff --git a/src/classes/tree/bst.h b/src/classes/tree/bst.h index 72608c00..386432bf 100644 --- a/src/classes/tree/bst.h +++ b/src/classes/tree/bst.h @@ -32,6 +32,12 @@ template class bst { */ void insert(T key) { root = __insert(root, key); } + /* + *search function. + *@param key: key to be searched. + */ + bool search(T key) { return __search(root, key); } + /* *remove function. *@param key: key to be removed. @@ -144,6 +150,19 @@ template class bst { return root; } + bool __search(node *root, T &key) { + while (root) { + if (root->info < key) { + root = root->right; + } else if (root->info > key) { + root = root->left; + } else { + return true; + } + } + return false; + } + node *__remove(node *root, T &key) { if (!root) { return root; diff --git a/tests/tree/avl.cc b/tests/tree/avl.cc index 38fd7ff2..b6302e19 100644 --- a/tests/tree/avl.cc +++ b/tests/tree/avl.cc @@ -5,8 +5,6 @@ TEST_CASE("checking insertions and traversals") { avl_tree a1; - avl_tree a2; - avl_tree a3; a1.insert(10); a1.insert(15); @@ -15,7 +13,33 @@ TEST_CASE("checking insertions and traversals") { std::vector v = {-150, 4, 10, 15}; std::vector inorder = a1.inorder(); REQUIRE(v == inorder); +} + +TEST_CASE("checking search") { + avl_tree a; + a.insert("hello"); + a.insert("world"); + a.insert("i'm"); + a.insert("spirosmag"); + REQUIRE(a.search("world") == true); + REQUIRE(a.search("im") == false); +} +TEST_CASE("checking removals") { + avl_tree a1; + a1.insert(10); + a1.insert(2); + a1.insert(190); + a1.insert(-20); + a1.insert(23); + a1.remove(190); + std::vector v = {-20, 2, 10, 23}; + std::vector inorder = a1.inorder(); + REQUIRE(v == inorder); +} + +TEST_CASE("checking inorder") { + avl_tree a2; a2.insert('g'); a2.insert('d'); a2.insert('w'); @@ -24,6 +48,7 @@ TEST_CASE("checking insertions and traversals") { std::vector _inorder = a2.inorder(); REQUIRE(_v == _inorder); + avl_tree a3; a3.insert("hello"); a3.insert("from"); a3.insert("mars"); @@ -33,15 +58,22 @@ TEST_CASE("checking insertions and traversals") { REQUIRE(__v == __inorder); } -TEST_CASE("checking removals") { - avl_tree a1; - a1.insert(10); - a1.insert(2); - a1.insert(190); - a1.insert(-20); - a1.insert(23); - a1.remove(190); - std::vector v = {-20, 2, 10, 23}; - std::vector inorder = a1.inorder(); - REQUIRE(v == inorder); +TEST_CASE("checking preorder") { + avl_tree a; + a.insert(10); + a.insert(5); + a.insert(-5); + a.insert(2); + std::vector __preorder = {5, -5, 2, 10}; + REQUIRE(a.preorder() == __preorder); +} + +TEST_CASE("checking postorder") { + avl_tree a; + a.insert(10); + a.insert(5); + a.insert(-5); + a.insert(2); + std::vector __postorder = {-5, 2, 10, 5}; + REQUIRE(a.postorder() == __postorder); } \ No newline at end of file diff --git a/tests/tree/bst.cc b/tests/tree/bst.cc index 99f279b8..7a7bd0cc 100644 --- a/tests/tree/bst.cc +++ b/tests/tree/bst.cc @@ -5,8 +5,6 @@ TEST_CASE("checking insertions and traversals") { bst b1; - bst b2; - bst b3; b1.insert(2); b1.insert(19); @@ -15,7 +13,42 @@ TEST_CASE("checking insertions and traversals") { std::vector v = {2, 5, 19}; std::vector inorder = b1.inorder(); REQUIRE(v == inorder); +} + +TEST_CASE("checking removals") { + bst b1; + b1.insert(10); + b1.insert(2); + b1.insert(190); + b1.insert(-20); + b1.insert(23); + + b1.remove(190); + std::vector v = {-20, 2, 10, 23}; + std::vector inorder = b1.inorder(); + REQUIRE(v == inorder); +} +TEST_CASE("checking search") { + bst b; + b.insert(1); + b.insert(10); + b.insert(-5); + b.insert(8); + REQUIRE(b.search(-5) == true); + REQUIRE(b.search(-8) == false); + + bst b1; + b1.insert("hello"); + b1.insert("i'm"); + b1.insert("spiros"); + b1.insert("maggioros"); + REQUIRE(b1.search("spiros") == true); + REQUIRE(b1.search("im") == false); +} + +TEST_CASE("checking inorder") { + bst b2; b2.insert('g'); b2.insert('k'); b2.insert('a'); @@ -24,6 +57,7 @@ TEST_CASE("checking insertions and traversals") { std::vector _inorder = b2.inorder(); REQUIRE(_v == _inorder); + bst b3; b3.insert("hello"); b3.insert("abraham"); b3.insert("cheers"); @@ -32,16 +66,22 @@ TEST_CASE("checking insertions and traversals") { REQUIRE(__v == __inorder); } -TEST_CASE("checking removals") { - bst b1; - b1.insert(10); - b1.insert(2); - b1.insert(190); - b1.insert(-20); - b1.insert(23); +TEST_CASE("checking preorder") { + bst b; + b.insert('g'); + b.insert('a'); + b.insert('b'); + b.insert('w'); + std::vector pre = {'g', 'a', 'b', 'w'}; + REQUIRE(b.preorder() == pre); +} - b1.remove(190); - std::vector v = {-20, 2, 10, 23}; - std::vector inorder = b1.inorder(); - REQUIRE(v == inorder); +TEST_CASE("checking postorder") { + bst b; + b.insert('g'); + b.insert('a'); + b.insert('b'); + b.insert('w'); + std::vector post = {'a', 'b', 'w', 'g'}; + REQUIRE(b.postorder() == post); } \ No newline at end of file diff --git a/tools/cpp_api/linked_list_api.cc b/tools/cpp_api/linked_list_api.cc deleted file mode 100644 index 330d67b1..00000000 --- a/tools/cpp_api/linked_list_api.cc +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef __cplusplus -#include "../../classes/list/linked_list.h" -#include -#endif - -namespace api { -void -}; \ No newline at end of file diff --git a/tutorial/avl.md b/tutorial/avl.md new file mode 100644 index 00000000..ed9e67a9 --- /dev/null +++ b/tutorial/avl.md @@ -0,0 +1,128 @@ +### Mini Tutorial for the AVL tree class + + avl_tree -- creates an avl tree. + +avl tree contains: + - insert + - remove + - search + - inorder + - preorder + - postorder + - visualize + +### **insert**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +//creates a tree with elements {4,5,10,13}; +``` + +### **remove**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); +//removes the element 4 from the tree. +``` + +### **remove**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); +//removes the element 4 from the tree. +``` + +### **search**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); + +//returns true if an element is in the tree. +if(a.search(4)){ + std::cout<< "element 4 found in the tree" << '\n'; +} +``` + +### **inorder**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); + +//returns the elements in inorder fashion. +std::vector in = a.inorder(); +``` + +### **preorder**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); + +//returns the elements in preorder fashion. +std::vector pre = a.preorder(); +``` + +### **postorder**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); + +//returns the elements in postorder fashion. +std::vector in = a.postorder(); +``` + +### **visualize**: +```cpp +#include + +avl_tree a; +a.insert(10); +a.insert(5); +a.insert(4); +a.insert(13); +a.remove(4); + +//returns a .dot file that can easily be previewed using +//vscode plugin for graphviz or local command line tools. +a.visualize(); +``` diff --git a/tutorial/graph.md b/tutorial/graph.md index 8b137891..7ff52592 100644 --- a/tutorial/graph.md +++ b/tutorial/graph.md @@ -1 +1,145 @@ +### Mini Tutorial for the Graph class + 1. graph -- unweighted graph + 2. weighted_graph -- weighted graph +graph class algorithms: + - dfs + - bfs + - connected_components + - cycle + - topological_sort + - bipartite + - visualize + +weighted_graph class algorithms: + - dfs + - bfs + - shortest_path + - connected_components + - cycle + - topological_sort + - prim + - bipartite + - visualize +There are also some functions for both classes like **has_edge(u, v)** that checks if an edge exists from node u to node v, **size()** that returns the number of elements in the graph, **empty()** that checks if a graph is empty and **empty()** that empties the graph. +### **DFS**: +```cpp +#include +graph g("directed); +g.add_edge(1, 2); +g.add_edge(4, 5); +g.add_edge(5 , 6); +g.add_edge(2, 4); + +//returns the path of the dfs. +std::vector dfs = g.dfs(); +``` + +### **BFS**: +```cpp +#include +graph g("directed); +g.add_edge(1, 2); +g.add_edge(4, 5); +g.add_edge(5 , 6); +g.add_edge(2, 4); + +//returns the path of the bfs. +std::vector bfs = g.bfs(); +``` + + +### **connected_components**: +```cpp +#include +graph g("undirected); +g.add_edge('a', 'b'); +g.add_edge('b','c'); +g.add_edge('g','h'); +//returns the number of connected components(islands) +std::cout << g.connected_components() << '\n'; +``` + +### **cycle**: +```cpp +#include +#include +graph g("undirected"); +g.add_edge("hello", "world"); +g.add_edge("hello", "mars"); +g.add_edge("mars", "world"); +//checks if a cycle exist in the graph. +if(g.cycle()){ + std::cout << "cycle detected" << '\n' +} +``` + +### **topological_sort**: +```cpp +#include +graph g("undirected"); +g.add_edge(1, 4); +g.add_edge(4, 5); +g.add_edge(5, 2); +g.add_edge(2, 8); + +//returns the topological order of the elements. +std::vector topo = g.topological_sort(); +``` +### **bipartite**: +```cpp +#include +graph g("undirected"); +g.add_edge(1, 4); +g.add_edge(4, 5); +g.add_edge(5, 2); +g.add_edge(2, 8); + +//checks if a graph is bipartite. +if(g.bipartite()){ + std::cout << "graph is bipartite" << '\n' +} +``` + +### **visualize**: +```cpp +#include +graph g("undirected"); +g.add_edge(1, 4); +g.add_edge(4, 5); +g.add_edge(5, 2); +g.add_edge(2, 8); + +// returns a .dot file that automatically opens +// using graphviz plugins on vscode(or locally with +// command lines). +g.visualize(); +``` + +### **shortest_path**: +```cpp +#include +weighted_graph g("undirected"); +g.add_edge(1, 4, 2); +g.add_edge(4, 5, 6); +g.add_edge(5, 2, 9); +g.add_edge(2, 8, 10); + +// returns the shortest path from 1 to 2. +std::cout << g.shortest_path(1, 2) << '\n'; +``` + +### **prim**: +```cpp +#include +weighted_graph g("undirected"); +g.add_edge("Athens", "Thessaloniki", 15); +g.add_edge("Patras", "Lamia", 50); +g.add_edge("Athens", "Lamia", 10); +g.add_edge("Kozani", "Thessaloniki", 13); +g.add_edge("Athens", "Kozani", 100); + +// returns the minimum spanning tree starting +// from the node Athens. +std::cout << g.prim("Athens") << '\n'; +``` \ No newline at end of file