--- tags: algorithms --- <style>.markdown-body { max-width: 1000px; }</style> # Data structures ## Circular Queue ```csharp= public class CircularQueue { int k; int head; int[] array; int count; public CircularQueue(int k) { this.k = k; array = new int[k]; head = 0; } public bool EnQueue(int value) { if(IsFull()) return false; array[(head + count)%k] = value; count++; return true; } public bool DeQueue() { if(IsEmpty()) return false; head = Next(head); count--; return true; } public int Front() { if(IsEmpty()) return -1; return array[head]; } public int Rear() { if(IsEmpty()) return -1; return array[(head + count - 1)%k]; } public bool IsEmpty() { return count == 0; } public bool IsFull(){ return count == k; } private int Next(int idx){ return (idx + 1) % k; } } ``` ## Suffix Array ```csharp= int[] BuildSuffixArray(string s){ int n = s.Length; Suffix[] suffixes = new Suffix[n]; for(int i = 0; i < n; i++){ suffixes[i] = new Suffix(i, s[i] - 'a'); //, (i + 1 < n) ? s[i+1] - 'a' : -1 ); } for (int i = 0; i < n; i++) { suffixes[i].nextRank = (i + 1 < n ? suffixes[i + 1].rank : -1); } Array.Sort(suffixes); //suffixes.D(); int[] indices = new int[n]; for(int length = 4; length < 2 * n; length <<=1){ //Rank compressing and comparing with previous suffix ranks int rank = 0, prevRank = suffixes[0].rank; suffixes[0].rank = 0; indices[suffixes[0].index] = 0; for (int i = 1; i < n; i++) { if (suffixes[i].rank == prevRank && suffixes[i].nextRank == suffixes[i - 1].nextRank) { prevRank = suffixes[i].rank; suffixes[i].rank = rank; } else { prevRank = suffixes[i].rank; suffixes[i].rank = ++rank; } indices[suffixes[i].index] = i; } for(int i = 0; i < n; i++){ int nextRankIndex = suffixes[i].index + length / 2; suffixes[i].nextRank = nextRankIndex < n ? suffixes[indices[nextRankIndex]].rank : -1; } Array.Sort(suffixes); } return suffixes.Select(s => s.index).ToArray(); } public class Suffix : IComparable<Suffix> { public int index; public int rank; public int nextRank; public Suffix(int index, int rank, int nextRank) { this.index = index; this.rank = rank; this.nextRank = nextRank; } public Suffix(int index, int rank):this(index, rank, 0) { } public int CompareTo(Suffix other) { if(rank != other.rank){ return rank.CompareTo(other.rank); } return nextRank.CompareTo(other.nextRank); } public override string ToString() { return $"index: {index}, rank: {rank}, nextRank: {nextRank}"; } } ``` ## Disjoined Set (Union Find) ```csharp= public class UnionFind { int[] _parents; int _roots; public UnionFind(int n) { _roots = n; _parents = new int[n]; Array.Fill(_parents, -1); } public int Find(int i) { return _parents[i] < 0 ? i : _parents[i] = Find(_parents[i]); } public int Union(int i, int j){ i = Find(i); j = Find(j); if(i != j){ _parents[i] += _parents[j]; _parents[j] = i; _roots--; } //$"Joined {i} and {j}".D(); //_parents.Print(); return -_parents[i]; } public int Roots => _roots; } ``` ## DeQueue ```csharp= public class Deque { int[] values; int left_ptr = 0; int right_ptr = 0; int n = 0; int count = 0; public int Count => count; public Deque(int n) { this.n = n; values = new int[n]; } public int First() { return values[left_ptr]; } public int Last() { return values[right_ptr]; } public void RemoveFirst() { if(left_ptr<n && left_ptr<right_ptr) left_ptr++; count--; } public void RemoveLast() { if(right_ptr>0 && right_ptr>left_ptr) right_ptr--; count--; } public void AddLast(int v) { if (count == 0) values[right_ptr] = v; else values[++right_ptr] = v; count++; } } ``` --- ## BitSet ```csharp= public class BitSet{ int [] bitSet; public int[] Set => bitSet; public BitSet(int size){ bitSet = new int[(size >> 5) + 1]; //divide by 32 } public bool Contains(int number){ int word = (number >> 5); //divide by 32 int offset = number & 0x1F; //modulo 32 //$"Checking number [{number}] as word {word}, offset {offset}. Result: {(bitSet[word] & (1 << offset))}".Dump(); return (bitSet[word] & (1 << offset)) != 0; } public void SetBit(int number){ int word = number >> 5; int offset = number & 0x1F; //$"Setting number [{number}] as word {word}, offset {offset}".Dump(); bitSet[word] |= (1 << offset); } public string ShowWord(int number, bool debug = false){ int word = number >> 5; if(debug){ int setNumber = 32 * word; for(int i = 0; i < 32; i++){ if((bitSet[word] & (1 << i)) != 0){ $"{setNumber} is set".Dump(); } setNumber++; } }; return $"[ {Convert.ToString(bitSet[word], 2).PadLeft(32, '0')} ]"; } } ``` ## Fenwick Tree ```csharp= public class FenwickTree{ int[] binaryTree; public FenwickTree(int[] array){ binaryTree = new int[array.Length+1]; for(int i = 1; i < binaryTree.Length; i++){ UpdateBinaryTree(binaryTree, i, array[i-1]); } } public void UpdateBinaryTree(int[] binaryTree, int index, int value){ while(index < binaryTree.Length){ binaryTree[index] += value; index += index & (-index); } } public int Query(int from, int to){ return Query(to) - Query(from-1); } public int Query(int index){ int sum = 0; index = index+1; while(index > 0){ sum += binaryTree[index]; index -= index & (-index); } return sum; } public int[] BinaryTree => binaryTree; } ``` ## Segment Tree ```csharp= public class SegmentTree { int n; List<int> data = new List<int>(); public SegmentTree(int[] a){ n = a.Length; for(int i = 0; i < n; i++){ data.Add(0); } for(int i = 0; i < n; i++){ data.Add(a[i]); } for(int p = n-1; p > 0; p--){ data[p] = Math.Min(data[p*2], data[p*2+1]); } } public int Min(int left, int right){ left = left + n; right = right + n; int min = Int32.MaxValue; while(left < right){ if((left & 1) == 1){ min = Math.Min(min, data[left]); left++; } if((right & 1) == 1){ right--; min = Math.Min(min, data[right]); } left >>= 1; right >>= 1; } return min; } public List<int> Data => data; } ```