Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new data structures: Trie & DSU #274

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions DataStructures/Trie/implementation/Trie.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Implementation of Trie data structure in C++.

/*
* Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_0 = obj->search(word);
* bool param_0 = obj->startsWith(word);
*/

#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;

// Create Trie node
class TrieNode {
public:
char val;
unordered_map<char, TrieNode*> children;
bool is_end;

// Constructor
TrieNode(char val = '\0', bool is_end = false) : val(val), is_end(is_end) {}
};

class Trie {
private:
TrieNode* root;

public:
// Create root node
Trie() {
root = new TrieNode();
}

// Insert a word into the Trie
void insert(const string& word) {
TrieNode* node = root;

for (char c : word) {
if (node->children.find(c) == node->children.end()) {
node->children[c] = new TrieNode(c);
}
node = node->children[c];
}
node->is_end = true; // Mark the end of a word
}

// Search for a word in the Trie
bool search(const string& word) {
TrieNode* node = root;

for (char c : word) {
if (node->children.find(c) == node->children.end()) {
return false;
}
node = node->children[c];
}

return node->is_end;
}

// Check if a word in Trie starts with prefix
bool startsWith(const string& prefix) {
TrieNode* node = root;

for (char c : prefix) {
if (node->children.find(c) == node->children.end()) {
return false;
}
node = node->children[c];
}

return true;
}
};

76 changes: 76 additions & 0 deletions DataStructures/Trie/implementation/Trie.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Implementation of Trie data structure in java.

/*
* Trie object will be instantiated and called as such:
* Trie obj = new Trie();
* obj.insert(word);
* boolean param_0 = obj.search(word);
* boolean param_1 = obj.startsWith(word);
*/

// Create Trie node
class TrieNode {
public char val;
public boolean isEnd;
public TrieNode[] children;

// Constructor
public TrieNode(char val) {
this.val = val;
this.isEnd = false;
this.children = new TrieNode[26];
}
}

class Trie {
private TrieNode root;

// Create root node
public Trie() {
root = new TrieNode(' ');
}

// Insert a word into the Trie
public void insert(String word) {
TrieNode node = root;

for (char c : word.toCharArray()) {
int index = c - 'a';
if (node.children[index] == null) {
node.children[index] = new TrieNode(c);
}
node = node.children[index];
}
node.isEnd = true; // Mark the end of a word
}

// Search for a word in the Trie
public boolean search(String word) {
TrieNode node = root;

for (char c : word.toCharArray()) {
int index = c - 'a';
if (node.children[index] == null) {
return false;
}
node = node.children[index];
}

return node.isEnd;
}

// Check if a word in Trie starts with prefix
public boolean startsWith(String prefix) {
TrieNode node = root;

for (char c : prefix.toCharArray()) {
int index = c - 'a';
if (node.children[index] == null) {
return false;
}
node = node.children[index];
}

return true;
}
}
51 changes: 51 additions & 0 deletions DataStructures/Trie/implementation/Trie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Implementation of Trie data structure in python.

# Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_0 = obj.search(word)
# param_1 = obj.startsWith(prefix)

class TrieNode:
def __init__(self, val='', is_end=False):
''' Create a Trie node '''
self.val = val
self.children = {}
self.is_end = is_end

class Trie:
def __init__(self):
''' Create the root node '''
self.root = TrieNode()

def insert(self, word: str) -> None:
''' Insert word in Trie '''
node = self.root

for c in word:
if c not in node.children:
node.children[c] = TrieNode(c)
node = node.children[c]

node.is_end = True

def search(self, word: str) -> bool:
''' Search for word in Trie '''
node = self.root

for c in word:
if c not in node.children: return False
node = node.children[c]

return node.is_end

def startsWith(self, prefix: str) -> bool:
''' Check if a word in Trie starts with prefix '''
node = self.root

for c in prefix:
if c not in node.children: return False
node = node.children[c]

return True

66 changes: 66 additions & 0 deletions DataStructures/UnionFind/implementation/UnionFind.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Implementation of Union Find / Disjoint Set Union (DSU) in C++

/*
* DSU object will be instantiated and called as such:
* UnionFind uf(n);
* uf.unite(x, y);
* int parent = uf.findRootOf(x);
* bool connected = uf.isConnected(x, y);
*/

#include <vector>
using namespace std;

class UnionFind {
private:
vector<int> root;
vector<int> rank;
int sets;

public:
// Constructor to create n sets
UnionFind(int n) {
root.resize(n);
rank.resize(n, 1);
sets = n;
for (int i = 0; i < n; ++i) {
root[i] = i;
}
}

// Find the root of x (with path compression)
int findRootOf(int x) {
if (root[x] != x) {
root[x] = findRootOf(root[x]); // Path compression
}
return root[x];
}

// Unite the sets containing x and y
void unite(int x, int y) {
int rootX = findRootOf(x);
int rootY = findRootOf(y);

// If they are already in the same set, return
if (rootX == rootY) {
return;
}

// Union by rank
if (rank[rootY] > rank[rootX]) {
root[rootX] = rootY;
rank[rootY] += rank[rootX];
} else {
root[rootY] = rootX;
rank[rootX] += rank[rootY];
}

sets--; // Decrease number of sets
}

// Check if x and y are connected (belong to the same set)
bool isConnected(int x, int y) {
return findRootOf(x) == findRootOf(y);
}
};

63 changes: 63 additions & 0 deletions DataStructures/UnionFind/implementation/UnionFind.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Implementation of Union Find / Disjoint Set Union (DSU) in java.

/*
* DSU object will be instantiated and called as such:
* UnionFind uf = new UnionFind(n);
* uf.unite(x, y);
* int parent = uf.findRootOf(x);
* boolean connected = uf.isConnected(x, y);
*/

class UnionFind {
private int[] root;
private int[] rank;
private int sets;

// Constructor to create n sets
public UnionFind(int n) {
root = new int[n];
rank = new int[n];
sets = n;

for (int i = 0; i < n; i++) {
root[i] = i;
rank[i] = 1;
}
}

// Find the root of x (with path compression)
public int findRootOf(int x) {
if (root[x] != x) {
root[x] = findRootOf(root[x]); // Path compression
}
return root[x];
}

// Unite the sets containing x and y
public void unite(int x, int y) {
int rootX = findRootOf(x);
int rootY = findRootOf(y);

// If they are already in the same set, return
if (rootX == rootY) {
return;
}

// Union by rank
if (rank[rootY] > rank[rootX]) {
root[rootX] = rootY;
rank[rootY] += rank[rootX];
} else {
root[rootY] = rootX;
rank[rootX] += rank[rootY];
}

sets--; // Decrease number of sets
}

// Check if x and y are connected (belong to the same set)
public boolean isConnected(int x, int y) {
return findRootOf(x) == findRootOf(y);
}
}

47 changes: 47 additions & 0 deletions DataStructures/UnionFind/implementation/UnionFind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Implementation of Union Find / Disjoint Set Union (DSU) in python

# DSU object will be instantiated and called as such:
# obj = UnionFind(n)
# obj.unite(x, y)
# parent = obj.findRootOf(x)
# connected = obj.isConnected(x, y)

class UnionFind:
def __init__(self, n):
''' Create n sets '''
self.root = [i for i in range(n)]
self.rank = [1] * n
self.sets = n

def findRootOf(self, x):
''' Find the root of x '''
while self.root[x] != x:
# Path compression
self.root[x] = self.root[self.root[x]]
x = self.root[x]
return x

def unite(self, x, y):
''' Unite the sets of x and y '''
rootX = self.findRootOf(x)
rootY = self.findRootOf(y)

# Return if they belong from the same sets
if rootX == rootY:
return

# Put the smaller set into the bigger set
if self.rank[rootY] > self.rank[rootX]:
self.root[rootX] = rootY
self.rank[rootY] += self.rank[rootX]
else:
self.root[rootY] = rootX
self.rank[rootX] += self.rank[rootY]

# Decrement set count
self.sets -= 1

def isConnected(self, x, y):
''' Check if x and y belong to the same set '''
return self.findRootOf(x) == self.findRootOf(y)