summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2020-07-18 14:00:48 +0200
committerTyge Løvset <[email protected]>2020-07-18 14:00:48 +0200
commitc4382861b07a4d48e86b9a4cca602aacf549e912 (patch)
tree26e7cd70aeef3e3150f55e9c37ca154da0428d9d
parent43605a63919dc328f50bcd4d304ca76ed30629f0 (diff)
downloadSTC-modified-c4382861b07a4d48e86b9a4cca602aacf549e912.tar.gz
STC-modified-c4382861b07a4d48e86b9a4cca602aacf549e912.zip
Added stc/cvecque.h : priority queue using vector as heap.
-rw-r--r--examples/geek7.c153
-rw-r--r--examples/heap.c36
-rw-r--r--stc/cvecque.h98
3 files changed, 287 insertions, 0 deletions
diff --git a/examples/geek7.c b/examples/geek7.c
new file mode 100644
index 00000000..b2bda51c
--- /dev/null
+++ b/examples/geek7.c
@@ -0,0 +1,153 @@
+/*
+Find the k smallest numbers after deleting given elements
+Given an array of integers, find the k smallest numbers after deleting given elements. In case of repeating elements delete only one instance in the given array for every instance of element present in the array containing the elements to be deleted.
+Assume that there are at least k elements left in the array after making n deletions.
+Examples:
+
+Input : array[] = { 5, 12, 33, 4, 56, 12, 20 }, del[] = { 12, 56, 5 }, k = 3
+Output : 4 12 20
+Explanation : After deletions { 33, 4, 12, 20 } will be left. Print top 3 smallest elements from it.
+
+Approach :
+Insert all the numbers in the hash map which are to be deleted from the array, so that we can check if the element in the array is also present in the Delete-array in O(1) time.
+Traverse through the array. Check if the element is present in the hash map.
+If present, erase it from the hash map. Else, insert it into a Min heap.
+After inserting all the elements excluding the ones which are to be deleted, Pop out k elements from the Min heap.
+*/
+
+#ifndef __cplusplus
+
+// C implementation of the approach
+
+#include <stdio.h>
+#include <stc/clist.h>
+#include <stc/cmap.h>
+#include <stc/cvec.h>
+
+declare_CMap(ii, int, int);
+
+// Find k minimum element from arr[0..m-1] after deleting
+// elements from del[0..n-1]
+void findElementsAfterDel(int arr[], int m, int del[],
+ int n, int k)
+{
+ // Hash Map of the numbers to be deleted
+ CMap_ii mp = cmap_init;
+ for (int i = 0; i < n; ++i) {
+
+ // Increment the count of del[i]
+ cmap_ii_at(&mp, del[i], 0)->value++;
+ }
+
+ priority_queue<int, vector<int>, greater<int> > heap;
+
+ for (int i = 0; i < m; ++i) {
+
+ // Search if the element is present
+ CMapEntry_ii *e = cmap_ii_get(&mp, arr[i]);
+ if (e != NULL) {
+
+ // Decrement its frequency
+ e->value--;
+
+ // If the frequency becomes 0,
+ // erase it from the map
+ if (e->value == 0)
+ cmap_ii_eraseEntry(&mp, e);
+ }
+
+ // Else push it in the min heap
+ else
+ heap.push(arr[i]);
+ }
+
+ // Print top k elements in the min heap
+ for (int i = 0; i < k; ++i) {
+ cout << heap.top() << " ";
+
+ // Pop the top element
+ heap.pop();
+ }
+}
+
+int main()
+{
+ int array[] = { 5, 12, 33, 4, 56, 12, 20 };
+ int m = sizeof(array) / sizeof(array[0]);
+
+ int del[] = { 12, 56, 5 };
+ int n = sizeof(del) / sizeof(del[0]);
+
+ int k = 3;
+
+ findElementsAfterDel(array, m, del, n, k);
+ return 0;
+}
+
+#else // =====================================================
+// C++ implementation of the approach
+
+#include <iostream>
+#include <queue>
+#include <unordered_map>
+#include <vector>
+using namespace std;
+
+// Find k minimum element from arr[0..m-1] after deleting
+// elements from del[0..n-1]
+void findElementsAfterDel(int arr[], int m, int del[],
+ int n, int k)
+{
+ // Hash Map of the numbers to be deleted
+ unordered_map<int, int> mp;
+ for (int i = 0; i < n; ++i) {
+
+ // Increment the count of del[i]
+ mp[del[i]]++;
+ }
+
+ priority_queue<int, vector<int>, greater<int> > heap;
+
+ for (int i = 0; i < m; ++i) {
+
+ // Search if the element is present
+ if (mp.find(arr[i]) != mp.end()) {
+
+ // Decrement its frequency
+ mp[arr[i]]--;
+
+ // If the frequency becomes 0,
+ // erase it from the map
+ if (mp[arr[i]] == 0)
+ mp.erase(arr[i]);
+ }
+
+ // Else push it in the min heap
+ else
+ heap.push(arr[i]);
+ }
+
+ // Print top k elements in the min heap
+ for (int i = 0; i < k; ++i) {
+ cout << heap.top() << " ";
+
+ // Pop the top element
+ heap.pop();
+ }
+}
+
+int main()
+{
+ int array[] = { 5, 12, 33, 4, 56, 12, 20 };
+ int m = sizeof(array) / sizeof(array[0]);
+
+ int del[] = { 12, 56, 5 };
+ int n = sizeof(del) / sizeof(del[0]);
+
+ int k = 3;
+
+ findElementsAfterDel(array, m, del, n, k);
+ return 0;
+}
+
+#endif \ No newline at end of file
diff --git a/examples/heap.c b/examples/heap.c
new file mode 100644
index 00000000..f9bc59e3
--- /dev/null
+++ b/examples/heap.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <time.h>
+#include "stc/cvecque.h"
+#include "stc/crandom.h"
+
+declare_CVec(f, float);
+declare_CVecque(f);
+
+int main()
+{
+ //float arr[] = {1, 3, 6, 5, 9, 8, -2};
+ float arr[] = {9., 3., 5., 10., 2., 4., 16., 7., 12., 8.};
+ uint32_t seed = time(NULL);
+ pcg32_random_t pcg = pcg32_seed(seed, 0);
+ int N = 30000000, M = 100;
+ CVec_f vec = cvec_init;
+ clock_t start = clock();
+ for (int i=0; i<N; ++i) cvec_f_pushBack(&vec, pcg32_random(&pcg)); // arr[i]);
+ cvec_f_queueify(&vec);
+ printf("\n\nqueueified: %f\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+
+ for (int i=0; i<M; ++i) printf("%.0f ", vec.data[i]);
+ puts("\n");
+ for (int i=0; i<M; ++i) printf("%.0f ", cvecque_f_pop(&vec));
+ start = clock();
+ for (int i=M; i<N; ++i) cvecque_f_pop(&vec);
+ printf("\n\npopped: %f\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+ printf("size: %zu\n", cvec_size(vec));
+ pcg = pcg32_seed(seed, 0);
+ start = clock();
+ for (int i=0; i<N; ++i) cvecque_f_push(&vec, pcg32_random(&pcg)); // arr[i]);
+ printf("pushed: %f\n", (clock() - start) / (float) CLOCKS_PER_SEC);
+ for (int i=0; i<M; ++i) printf("%.0f ", vec.data[i]);
+ puts("\n");
+ for (int i=0; i<M; ++i) printf("%.0f ", cvecque_f_pop(&vec));
+}
diff --git a/stc/cvecque.h b/stc/cvecque.h
new file mode 100644
index 00000000..7b0175e4
--- /dev/null
+++ b/stc/cvecque.h
@@ -0,0 +1,98 @@
+/* MIT License
+ *
+ * Copyright (c) 2020 Tyge Løvset, NORCE, www.norceresearch.no
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* Priority queue using CVec as heap. */
+
+#ifndef CVECQUE__H__
+#define CVECQUE__H__
+
+#include "cvec.h"
+
+/* Requires declare_CVec(tag, ...) to be declared */
+#define declare_CVecque(tag) \
+ \
+STC_API void \
+cvec_##tag##_queueify(CVec_##tag* self); \
+STC_API CVecValue_##tag \
+cvecque_##tag##_erase(CVec_##tag* self, size_t i); \
+STC_INLINE CVecValue_##tag \
+cvecque_##tag##_top(CVec_##tag* self) {return self->data[0];} \
+STC_INLINE CVecValue_##tag \
+cvecque_##tag##_pop(CVec_##tag* self) {return cvecque_##tag##_erase(self, 0);} \
+STC_API void \
+cvecque_##tag##_push(CVec_##tag* self, CVecValue_##tag value); \
+ \
+implement_CVecque(tag) \
+typedef CVec_##tag CVecdeque_##tag
+
+/* -------------------------- IMPLEMENTATION ------------------------- */
+
+#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION)
+#define implement_CVecque(tag) \
+ \
+STC_INLINE void \
+_cvecque_##tag##_siftDown(CVecValue_##tag* arr, size_t i, size_t n) { \
+ size_t r = i, c = i << 1; \
+ while (c <= n) { \
+ if (c < n && arr[c] > arr[c + 1]) \
+ ++c; \
+ if (arr[r] > arr[c]) { \
+ CVecValue_##tag t = arr[r]; arr[r] = arr[c]; arr[r = c] = t; \
+ } else \
+ return; \
+ c <<= 1; \
+ } \
+} \
+ \
+STC_API CVecValue_##tag \
+cvecque_##tag##_erase(CVec_##tag* self, size_t i) { \
+ CVecValue_##tag ret = self->data[i]; \
+ self->data[i] = cvec_##tag##_back(*self); \
+ cvec_##tag##_popBack(self); \
+ _cvecque_##tag##_siftDown(self->data - 1, i + 1, cvec_size(*self)); \
+ return ret; \
+} \
+ \
+STC_API void \
+cvecque_##tag##_push(CVec_##tag* self, CVecValue_##tag value) { \
+ cvec_##tag##_pushBack(self, value); \
+ size_t n = cvec_size(*self), i = n; \
+ CVecValue_##tag *arr = self->data - 1; \
+ for (; i > 1 && arr[i >> 1] > value; i >>= 1) \
+ arr[i] = arr[i >> 1]; \
+ arr[i] = value; \
+} \
+ \
+STC_API void \
+cvec_##tag##_queueify(CVec_##tag* self) { \
+ size_t n = cvec_size(*self); \
+ CVecValue_##tag *arr = self->data - 1; \
+ for (size_t i = n >> 1; i; --i) \
+ _cvecque_##tag##_siftDown(arr, i, n); \
+}
+
+#else
+#define implement_CVecque(tag)
+#endif
+
+#endif