Skip to content

Commit 7c3e098

Browse files
authored
Merge pull request #13 from monkey0722/feature/20250420
feature: 20250420
2 parents 1acb202 + 46f54ca commit 7c3e098

File tree

6 files changed

+566
-3
lines changed

6 files changed

+566
-3
lines changed

.vscode/c_cpp_properties.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
{
44
"name": "Mac",
55
"includePath": [
6-
"${workspaceFolder}/**", // Overall project path
7-
"/opt/homebrew/include" // M1~ Standard path for Mac
6+
"${workspaceFolder}/**",
7+
"/opt/homebrew/include"
88
],
99
"defines": [],
1010
"macFrameworkPath": [
@@ -17,4 +17,4 @@
1717
}
1818
],
1919
"version": 4
20-
}
20+
}

.vscode/settings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"C_Cpp.default.compilerPath": "/usr/bin/clang",
3+
"C_Cpp.default.cppStandard": "c++20",
4+
"C_Cpp.default.includePath": [
5+
"${workspaceFolder}/src"
6+
],
7+
"C_Cpp.default.intelliSenseMode": "clang-x64"
8+
}

src/graph/kruskal.hpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#ifndef KRUSKAL_HPP
2+
#define KRUSKAL_HPP
3+
4+
#include <algorithm>
5+
#include <concepts>
6+
#include <iostream>
7+
#include <vector>
8+
9+
/**
10+
* @brief Edge structure for Kruskal's algorithm
11+
*/
12+
struct KruskalEdge {
13+
int from;
14+
int to;
15+
long long weight;
16+
17+
// Operator for sorting edges by weight
18+
bool operator<(const KruskalEdge& other) const {
19+
return weight < other.weight;
20+
}
21+
};
22+
23+
/**
24+
* @brief Disjoint Set Union (DSU) data structure for Kruskal's algorithm
25+
*/
26+
class DisjointSet {
27+
private:
28+
std::vector<int> parent;
29+
std::vector<int> rank;
30+
31+
public:
32+
/**
33+
* @brief Initialize a DSU with n elements
34+
* @param n Number of elements
35+
*/
36+
DisjointSet(int n) : parent(n), rank(n, 0) {
37+
for (int i = 0; i < n; i++) {
38+
parent[i] = i; // Each element is its own parent initially
39+
}
40+
}
41+
42+
/**
43+
* @brief Find the representative of the set containing x
44+
* @param x Element to find
45+
* @return Representative of the set
46+
*/
47+
int find(int x) {
48+
if (parent[x] != x) {
49+
parent[x] = find(parent[x]); // Path compression
50+
}
51+
return parent[x];
52+
}
53+
54+
/**
55+
* @brief Union of two sets
56+
* @param x First element
57+
* @param y Second element
58+
* @return True if x and y were in different sets, false otherwise
59+
*/
60+
bool unite(int x, int y) {
61+
int rootX = find(x);
62+
int rootY = find(y);
63+
64+
if (rootX == rootY) {
65+
return false; // Already in the same set
66+
}
67+
68+
// Union by rank
69+
if (rank[rootX] < rank[rootY]) {
70+
parent[rootX] = rootY;
71+
} else if (rank[rootX] > rank[rootY]) {
72+
parent[rootY] = rootX;
73+
} else {
74+
parent[rootY] = rootX;
75+
rank[rootX]++;
76+
}
77+
78+
return true;
79+
}
80+
};
81+
82+
/**
83+
* @brief Kruskal's algorithm for finding the Minimum Spanning Tree (MST) of a graph
84+
*
85+
* @param n Number of vertices in the graph
86+
* @param edges Vector of edges in the graph
87+
* @return Vector of edges that form the MST and the total weight of the MST
88+
*/
89+
std::pair<std::vector<KruskalEdge>, long long> kruskal(int n, std::vector<KruskalEdge>& edges) {
90+
// Sort edges by weight
91+
std::sort(edges.begin(), edges.end());
92+
93+
DisjointSet dsu(n);
94+
std::vector<KruskalEdge> mst;
95+
long long totalWeight = 0;
96+
97+
for (const auto& edge : edges) {
98+
if (dsu.unite(edge.from, edge.to)) {
99+
// This edge is part of the MST
100+
mst.push_back(edge);
101+
totalWeight += edge.weight;
102+
103+
// If we have n-1 edges, we have a complete MST
104+
if (mst.size() == n - 1) {
105+
break;
106+
}
107+
}
108+
}
109+
110+
return {mst, totalWeight};
111+
}
112+
113+
/**
114+
* @brief Check if the graph is connected
115+
*
116+
* @param n Number of vertices
117+
* @param mst The MST edges
118+
* @return True if the graph is connected, false otherwise
119+
*/
120+
bool isConnected(int n, const std::vector<KruskalEdge>& mst) {
121+
return mst.size() == n - 1;
122+
}
123+
124+
#endif // KRUSKAL_HPP

src/search/binary_search.hpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#ifndef BINARY_SEARCH_HPP
2+
#define BINARY_SEARCH_HPP
3+
4+
#include <concepts>
5+
#include <functional>
6+
#include <vector>
7+
8+
namespace clavis {
9+
namespace search {
10+
11+
/**
12+
* @brief Binary search algorithm for finding an element in a sorted array
13+
*
14+
* @tparam T Type of elements in the array (must be comparable)
15+
* @param arr Sorted array to search in
16+
* @param target Element to search for
17+
* @return Index of the target element if found, -1 otherwise
18+
*/
19+
template <typename T>
20+
requires std::totally_ordered<T>
21+
int binary_search(const std::vector<T>& arr, const T& target) {
22+
int left = 0;
23+
int right = arr.size() - 1;
24+
25+
while (left <= right) {
26+
int mid = left + (right - left) / 2; // Avoid potential overflow
27+
28+
if (arr[mid] == target) {
29+
return mid; // Found the target
30+
} else if (arr[mid] < target) {
31+
left = mid + 1; // Search in the right half
32+
} else {
33+
right = mid - 1; // Search in the left half
34+
}
35+
}
36+
37+
return -1; // Target not found
38+
}
39+
40+
/**
41+
* @brief Lower bound binary search - finds the first element not less than the target
42+
*
43+
* @tparam T Type of elements in the array (must be comparable)
44+
* @param arr Sorted array to search in
45+
* @param target Element to search for
46+
* @return Index of the first element not less than target, or arr.size() if all elements are less than target
47+
*/
48+
template <typename T>
49+
requires std::totally_ordered<T>
50+
int lower_bound(const std::vector<T>& arr, const T& target) {
51+
int left = 0;
52+
int right = arr.size(); // Note: right is arr.size(), not arr.size() - 1
53+
54+
while (left < right) {
55+
int mid = left + (right - left) / 2;
56+
57+
if (arr[mid] < target) {
58+
left = mid + 1;
59+
} else {
60+
right = mid;
61+
}
62+
}
63+
64+
return left; // Returns arr.size() if all elements are less than target
65+
}
66+
67+
/**
68+
* @brief Upper bound binary search - finds the first element greater than the target
69+
*
70+
* @tparam T Type of elements in the array (must be comparable)
71+
* @param arr Sorted array to search in
72+
* @param target Element to search for
73+
* @return Index of the first element greater than target, or arr.size() if no such element exists
74+
*/
75+
template <typename T>
76+
requires std::totally_ordered<T>
77+
int upper_bound(const std::vector<T>& arr, const T& target) {
78+
int left = 0;
79+
int right = arr.size(); // Note: right is arr.size(), not arr.size() - 1
80+
81+
while (left < right) {
82+
int mid = left + (right - left) / 2;
83+
84+
if (arr[mid] <= target) {
85+
left = mid + 1;
86+
} else {
87+
right = mid;
88+
}
89+
}
90+
91+
return left; // Returns arr.size() if all elements are less than or equal to target
92+
}
93+
94+
/**
95+
* @brief Binary search on a predicate function
96+
*
97+
* @tparam T Type of elements in the search space
98+
* @param left Left boundary of the search space (inclusive)
99+
* @param right Right boundary of the search space (exclusive)
100+
* @param predicate Function that returns true for elements that satisfy the condition
101+
* @return The first element in the range [left, right) for which predicate returns true, or right if none exists
102+
*/
103+
template <typename T>
104+
requires std::integral<T>
105+
T binary_search_predicate(T left, T right, const std::function<bool(T)>& predicate) {
106+
while (left < right) {
107+
T mid = left + (right - left) / 2;
108+
109+
if (predicate(mid)) {
110+
right = mid;
111+
} else {
112+
left = mid + 1;
113+
}
114+
}
115+
116+
return left; // Returns right if no element satisfies the predicate
117+
}
118+
119+
} // namespace search
120+
} // namespace clavis
121+
122+
#endif // BINARY_SEARCH_HPP

0 commit comments

Comments
 (0)