mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-02-09 05:27:11 +08:00
Merge pull request #2 from TheAlgorithms/master
update fork TheAlgorithms/C-Plus-Plus
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
* [Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/stk/stack.h)
|
||||
* [Test Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/stk/test_stack.cpp)
|
||||
* [Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/Tree.cpp)
|
||||
* [Trie Modern](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/trie_modern.cpp)
|
||||
* [Trie Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structure/trie_tree.cpp)
|
||||
|
||||
## Dynamic Programming
|
||||
@@ -72,6 +73,9 @@
|
||||
* [Searching Of Element In Dynamic Array](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/searching_of_element_in_dynamic_array.cpp)
|
||||
* [Tree Height](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/tree_height.cpp)
|
||||
|
||||
## Geometry
|
||||
* [Line Segment Intersection](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/line_segment_intersection.cpp)
|
||||
|
||||
## Graph
|
||||
* [Bfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/BFS.cpp)
|
||||
* [Bridge Finding With Tarjan Algorithm](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/bridge_finding_with_tarjan_algorithm.cpp)
|
||||
@@ -111,6 +115,7 @@
|
||||
* [Fibonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/fibonacci.cpp)
|
||||
* [Greatest Common Divisor](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/greatest_common_divisor.cpp)
|
||||
* [Greatest Common Divisor Euclidean](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/greatest_common_divisor_euclidean.cpp)
|
||||
* [Least Common Multiple](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/least_common_multiple.cpp)
|
||||
* [Modular Inverse Fermat Little Theorem](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/modular_inverse_fermat_little_theorem.cpp)
|
||||
* [Number Of Positive Divisors](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/number_of_positive_divisors.cpp)
|
||||
* [Power For Huge Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/math/power_for_huge_numbers.cpp)
|
||||
@@ -196,7 +201,7 @@
|
||||
* [Non Recursive Merge Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/non_recursive_merge_sort.cpp)
|
||||
* [Numericstringsort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/NumericStringSort.cpp)
|
||||
* [Oddeven Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/OddEven%20Sort.cpp)
|
||||
* [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Quick%20Sort.cpp)
|
||||
* [Quick Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/quick_sort.cpp)
|
||||
* [Radix Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Radix%20Sort.cpp)
|
||||
* [Selection Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Selection%20Sort.cpp)
|
||||
* [Shell Sort](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/sorting/Shell%20Sort.cpp)
|
||||
|
||||
167
data_structure/trie_modern.cpp
Normal file
167
data_structure/trie_modern.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Copyright 2020 @author Anmol3299
|
||||
* @file
|
||||
*
|
||||
* A basic implementation of trie class to store only lower-case strings.
|
||||
*/
|
||||
#include <iostream> // for io operations
|
||||
#include <memory> // for std::shared_ptr<>
|
||||
#include <string> // for std::string class
|
||||
|
||||
/**
|
||||
* A basic implementation of trie class to store only lower-case strings.
|
||||
* You can extend the implementation to all the ASCII characters by changing the
|
||||
* value of @ ALPHABETS to 128.
|
||||
*/
|
||||
class Trie {
|
||||
private:
|
||||
static constexpr size_t ALPHABETS = 26;
|
||||
|
||||
/**
|
||||
* Structure of trie node.
|
||||
* This struct doesn't need a constructor as we are initializing using
|
||||
* intializer list which is more efficient than if we had done so with
|
||||
* constructor.
|
||||
*/
|
||||
struct TrieNode {
|
||||
// An array of pointers of size 26 which tells if a character of word is
|
||||
// present or not.
|
||||
std::shared_ptr<TrieNode> character[ALPHABETS]{nullptr};
|
||||
|
||||
bool isEndOfWord{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to check if a node has some children which can form words.
|
||||
* @param node whose character array of pointers need to be checked for
|
||||
* children.
|
||||
* @return if a child is found, it returns @ true, else it returns @ false.
|
||||
*/
|
||||
inline static bool hasChildren(std::shared_ptr<TrieNode> node) {
|
||||
for (size_t i = 0; i < ALPHABETS; i++) {
|
||||
if (node->character[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A recursive helper function to remove a word from the trie. First, it
|
||||
* recursively traverses to the location of last character of word in the
|
||||
* trie. However, if the word is not found, the function returns a runtime
|
||||
* error. Upon successfully reaching the last character of word in trie, if
|
||||
* sets the isEndOfWord to false and deletes the node if and only if it has
|
||||
* no children, else it returns the current node.
|
||||
* @param word is the string which needs to be removed from trie.
|
||||
* @param curr is the current node we are at.
|
||||
* @param index is the index of the @word we are at.
|
||||
* @return if current node has childern, it returns @ curr, else it returns
|
||||
* nullptr.
|
||||
* @throw a runtime error in case @ word is not found in the trie.
|
||||
*/
|
||||
std::shared_ptr<TrieNode> removeWordHelper(const std::string& word,
|
||||
std::shared_ptr<TrieNode> curr,
|
||||
size_t index) {
|
||||
if (word.size() == index) {
|
||||
if (curr->isEndOfWord) {
|
||||
curr->isEndOfWord = false;
|
||||
}
|
||||
if (hasChildren(curr)) {
|
||||
return curr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t idx = word[index] - 'a';
|
||||
|
||||
// Throw a runtime error in case the user enters a word which is not
|
||||
// present in the trie.
|
||||
if (!curr->character[idx]) {
|
||||
throw std::runtime_error(std::move(std::string("Word not found.")));
|
||||
}
|
||||
|
||||
curr->character[idx] =
|
||||
removeWordHelper(word, curr->character[idx], index + 1);
|
||||
|
||||
// This if condition checks if the node has some childern.
|
||||
// The 1st if check, i.e. (curr->character[idx]) is checked specifically
|
||||
// because if the older string is a prefix of some other string, then,
|
||||
// there would be no need to check all 26 characters. Example- str1 =
|
||||
// abbey, str2 = abbex and we want to delete string "abbey", then in
|
||||
// this case, there would be no need to check all characters for the
|
||||
// chars a,b,b.
|
||||
if (curr->character[idx] || hasChildren(curr)) {
|
||||
return curr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
// constructor to initialise the root of the trie.
|
||||
Trie() : m_root(std::make_shared<TrieNode>()) {}
|
||||
|
||||
/**
|
||||
* Insert a word into the trie.
|
||||
* @param word which needs to be inserted into the string.
|
||||
*/
|
||||
void insert(const std::string& word) {
|
||||
auto curr = m_root;
|
||||
for (char ch : word) {
|
||||
size_t index = ch - 'a';
|
||||
|
||||
// if a node for current word is not already present in trie, create
|
||||
// a new node for it.
|
||||
if (!curr->character[index]) {
|
||||
curr->character[index] = std::make_shared<TrieNode>();
|
||||
}
|
||||
|
||||
curr = curr->character[index];
|
||||
}
|
||||
curr->isEndOfWord = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search if a word is present in trie or not.
|
||||
* @param word which is needed to be searched in the trie.
|
||||
* @return True if the word is found in trie and isEndOfWord is set to true.
|
||||
* @return False if word is not found in trie or isEndOfWord is set to
|
||||
* false.
|
||||
*/
|
||||
bool search(const std::string& word) {
|
||||
auto curr = m_root;
|
||||
for (char ch : word) {
|
||||
size_t index = ch - 'a';
|
||||
|
||||
// if any node for a character is not found, then return that the
|
||||
// word cannot be formed.
|
||||
if (!curr->character[index]) {
|
||||
return false;
|
||||
}
|
||||
curr = curr->character[index];
|
||||
}
|
||||
return curr->isEndOfWord;
|
||||
}
|
||||
|
||||
// Function to remove the word which calls the helper function.
|
||||
void removeWord(const std::string& word) {
|
||||
m_root = removeWordHelper(word, m_root, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
// data member to store the root of the trie.
|
||||
std::shared_ptr<TrieNode> m_root;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
int main() {
|
||||
Trie trie;
|
||||
trie.insert("hel");
|
||||
trie.insert("hello");
|
||||
trie.removeWord("hel");
|
||||
std::cout << trie.search("hello") << '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
101
geometry/line_segment_intersection.cpp
Normal file
101
geometry/line_segment_intersection.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief check whether two line segments intersect each other
|
||||
* or not.
|
||||
*/
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Define a Point.
|
||||
*/
|
||||
struct Point {
|
||||
int x; /// Point respect to x coordinate
|
||||
int y; /// Point respect to y coordinate
|
||||
};
|
||||
|
||||
/**
|
||||
* intersect returns true if segments of two line intersects and
|
||||
* false if they do not. It calls the subroutines direction
|
||||
* which computes the orientation.
|
||||
*/
|
||||
struct SegmentIntersection {
|
||||
inline bool intersect(Point first_point, Point second_point,
|
||||
Point third_point, Point forth_point) {
|
||||
int direction1 = direction(third_point, forth_point, first_point);
|
||||
int direction2 = direction(third_point, forth_point, second_point);
|
||||
int direction3 = direction(first_point, second_point, third_point);
|
||||
int direction4 = direction(first_point, second_point, forth_point);
|
||||
|
||||
if ((direction1 < 0 || direction2 > 0) && (direction3 < 0 ||
|
||||
direction4 > 0))
|
||||
return true;
|
||||
|
||||
else if (direction1 == 0 && on_segment(third_point, forth_point,
|
||||
first_point))
|
||||
return true;
|
||||
|
||||
else if (direction2 == 0 && on_segment(third_point, forth_point,
|
||||
second_point))
|
||||
return true;
|
||||
|
||||
else if (direction3 == 0 && on_segment(first_point, second_point,
|
||||
third_point))
|
||||
return true;
|
||||
|
||||
else if (direction3 == 0 && on_segment(first_point, second_point,
|
||||
forth_point))
|
||||
return true;
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* We will find direction of line here respect to @first_point.
|
||||
* Here @second_point and @third_point is first and second points
|
||||
* of the line respectively. we want a method to determine which way a
|
||||
* given angle these three points turns. If returned number is negative,
|
||||
* then the angle is counter-clockwise. That means the line is going to
|
||||
* right to left. We will fount angle as clockwise if the method returns
|
||||
* positive number.
|
||||
*/
|
||||
inline int direction(Point first_point, Point second_point,
|
||||
Point third_point) {
|
||||
return ((third_point.x-first_point.x)*(second_point.y-first_point.y))-
|
||||
((second_point.x-first_point.x) * (third_point.y-first_point.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method determines whether a point known to be colinear
|
||||
* with a segment lies on that segment.
|
||||
*/
|
||||
inline bool on_segment(Point first_point, Point second_point,
|
||||
Point third_point) {
|
||||
if (std::min(first_point.x, second_point.x) <= third_point.x &&
|
||||
third_point.x <= std::max(first_point.x, second_point.x) &&
|
||||
std::min(first_point.y, second_point.y) <= third_point.y &&
|
||||
third_point.y <= std::max(first_point.y, second_point.y))
|
||||
return true;
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the main function to test whether the algorithm is
|
||||
* working well.
|
||||
*/
|
||||
int main() {
|
||||
SegmentIntersection segment;
|
||||
Point first_point, second_point, third_point, forth_point;
|
||||
|
||||
std::cin >> first_point.x >> first_point.y;
|
||||
std::cin >> second_point.x >> second_point.y;
|
||||
std::cin >> third_point.x >> third_point.y;
|
||||
std::cin >> forth_point.x >> forth_point.y;
|
||||
|
||||
printf("%d", segment.intersect(first_point, second_point, third_point,
|
||||
forth_point));
|
||||
std::cout << std::endl;
|
||||
}
|
||||
70
math/least_common_multiple.cpp
Normal file
70
math/least_common_multiple.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright 2020 @author tjgurwara99
|
||||
* @file
|
||||
*
|
||||
* A basic implementation of LCM function
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Function for finding greatest common divisor of two numbers.
|
||||
* @params two integers x and y whose gcd we want to find.
|
||||
* @return greatest common divisor of x and y.
|
||||
*/
|
||||
unsigned int gcd(unsigned int x, unsigned int y) {
|
||||
if (x == 0) {
|
||||
return y;
|
||||
}
|
||||
if (y == 0) {
|
||||
return x;
|
||||
}
|
||||
if (x == y) {
|
||||
return x;
|
||||
}
|
||||
if (x > y) {
|
||||
// The following is valid because we have checked whether y == 0
|
||||
|
||||
int temp = x / y;
|
||||
return gcd(y, x - temp * y);
|
||||
}
|
||||
// Again the following is valid because we have checked whether x == 0
|
||||
|
||||
int temp = y / x;
|
||||
return gcd(x, y - temp * x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for finding the least common multiple of two numbers.
|
||||
* @params integer x and y whose lcm we want to find.
|
||||
* @return lcm of x and y using the relation x * y = gcd(x, y) * lcm(x, y)
|
||||
*/
|
||||
unsigned int lcm(unsigned int x, unsigned int y) { return x * y / gcd(x, y); }
|
||||
|
||||
/**
|
||||
* Function for testing the lcm() functions with some assert statements.
|
||||
*/
|
||||
void tests() {
|
||||
// First test on lcm(5,10) == 10
|
||||
assert(((void)"LCM of 5 and 10 is 10 but lcm function gives a different "
|
||||
"result.\n",
|
||||
lcm(5, 10) == 10));
|
||||
std::cout << "First assertion passes: LCM of 5 and 10 is " << lcm(5, 10)
|
||||
<< std::endl;
|
||||
|
||||
// Second test on lcm(2,3) == 6 as 2 and 3 are coprime (prime in fact)
|
||||
assert(((void)"LCM of 2 and 3 is 6 but lcm function gives a different "
|
||||
"result.\n",
|
||||
lcm(2, 3) == 6));
|
||||
std::cout << "Second assertion passes: LCM of 2 and 3 is " << lcm(2, 3)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
int main() {
|
||||
tests();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user