]> git.kaiwu.me - klib.git/commitdiff
Graph related routines. Unfinished. DON'T USE!
authorHeng Li <lh3@live.co.uk>
Wed, 28 Dec 2011 22:24:24 +0000 (17:24 -0500)
committerHeng Li <lh3@live.co.uk>
Wed, 28 Dec 2011 22:24:24 +0000 (17:24 -0500)
kgraph.h [new file with mode: 0644]
test/kgraph_test.c [new file with mode: 0644]

diff --git a/kgraph.h b/kgraph.h
new file mode 100644 (file)
index 0000000..af008ef
--- /dev/null
+++ b/kgraph.h
@@ -0,0 +1,79 @@
+#ifndef AC_KGRAPH_H
+#define AC_KGRAPH_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "khash.h"
+#include "kbtree.h"
+
+typedef unsigned kgint_t;
+
+#define kgraph_t(name) kh_##name##_t
+
+#define __KG_BASIC(name, SCOPE, vertex_t, arc_t, ehn) \
+       SCOPE kgraph_t(name) *kg_init_##name(void) { return kh_init(name); } \
+       SCOPE void kg_destroy_##name(kgraph_t(name) *g) { \
+               khint_t k; \
+               if (g == 0) return; \
+               for (k = kh_begin(g); k != kh_end(g); ++k) \
+                       if (kh_exist(g, k)) kh_destroy(ehn, kh_val(g, k)._arc); \
+               kh_destroy(name, g); \
+       } \
+       SCOPE vertex_t *kg_get_v_##name(kgraph_t(name) *g, kgint_t v) { \
+               khint_t k = kh_get(name, g, v); \
+               return k == kh_end(g)? 0 : &kh_val(g, k); \
+       } \
+       SCOPE vertex_t *kg_put_v_##name(kgraph_t(name) *g, kgint_t v, int *absent) { \
+               khint_t k; \
+               k = kh_put(name, g, v, absent); \
+               if (*absent) kh_val(g, k)._arc = kh_init(ehn); \
+               return &kh_val(g, k); \
+       } \
+       SCOPE void kg_put_a_##name(kgraph_t(name) *g, kgint_t vbeg, kgint_t vend, int dir, arc_t **pb, arc_t **pe) { \
+               vertex_t *p; \
+               khint_t k; \
+               int absent; \
+               p = kg_put_v_##name(g, vbeg, &absent); \
+               k = kh_put(ehn, p->_arc, vend<<2|dir, &absent); \
+               *pb = &kh_val(p->_arc, k); \
+               p = kg_put_v_##name(g, vend, &absent); \
+               k = kh_put(ehn, p->_arc, vbeg<<2|(~dir&3), &absent); \
+               *pe = &kh_val(p->_arc, k); \
+       } \
+       SCOPE vertex_t *kg_del_v_##name(kgraph_t(name) *g, kgint_t v) { \
+               khint_t k, k0, k2, k3; \
+               khash_t(ehn) *h; \
+               k0 = k = kh_get(name, g, v); \
+               if (k == kh_end(g)) return 0; /* not present in the graph */ \
+               h = kh_val(g, k)._arc; \
+               for (k = kh_begin(h); k != kh_end(h); ++k) /* remove v from its neighbors */ \
+                       if (kh_exist(h, k)) { \
+                               k2 = kh_get(name, g, kh_key(h, k)>>2); \
+                               /* assert(k2 != kh_end(g)); */ \
+                               k3 = kh_get(ehn, kh_val(g, k2)._arc, v<<2|(~kh_key(h, k)&3)); \
+                               /* assert(k3 != kh_end(kh_val(g, k2)._arc)); */ \
+                               kh_del(ehn, kh_val(g, k2)._arc, k3); \
+                       } \
+               kh_destroy(ehn, h); \
+               kh_del(name, g, k0); \
+               return &kh_val(g, k0); \
+       }
+
+#define KGRAPH_PRINT(name, SCOPE) \
+       SCOPE void kg_print_##name(kgraph_t(name) *g) { \
+               khint_t k, k2; \
+               for (k = kh_begin(g); k != kh_end(g); ++k) \
+                       if (kh_exist(g, k)) { \
+                               printf("v %u\n", kh_key(g, k)); \
+                               for (k2 = kh_begin(kh_val(g, k)._arc); k2 != kh_end(kh_val(g, k)._arc); ++k2) \
+                                       if (kh_exist(kh_val(g, k)._arc, k2) && kh_key(g, k) < kh_key(kh_val(g, k)._arc, k2)>>2) \
+                                               printf("a %u%c%c%u\n", kh_key(g, k), "><"[kh_key(kh_val(g, k)._arc, k2)>>1&1], \
+                                                               "><"[kh_key(kh_val(g, k)._arc, k2)&1], kh_key(kh_val(g, k)._arc, k2)>>2); \
+                       } \
+       }
+
+#define KGRAPH_INIT(name, SCOPE, vertex_t, arc_t, ehn) \
+       KHASH_INIT2(name, SCOPE, kgint_t, vertex_t, 1, kh_int_hash_func, kh_int_hash_equal) \
+       __KG_BASIC(name, SCOPE, vertex_t, arc_t, ehn)
+
+#endif
diff --git a/test/kgraph_test.c b/test/kgraph_test.c
new file mode 100644 (file)
index 0000000..3da1cd7
--- /dev/null
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include "kgraph.h"
+
+KHASH_INIT2(e32, extern, uint32_t, int, 1, kh_int_hash_func, kh_int_hash_equal)
+
+typedef struct {
+       int i;
+       khash_t(e32) *_arc;
+} vertex_t;
+
+KGRAPH_INIT(g, extern, vertex_t, int, e32)
+KGRAPH_PRINT(g, extern)
+
+int main()
+{
+       int *pb, *pe;
+       kgraph_t(g) *g;
+       g = kg_init_g();
+       kg_put_a_g(g, 10, 20, 0, &pb, &pe);
+       kg_put_a_g(g, 20, 30, 0, &pb, &pe);
+       kg_put_a_g(g, 30, 10, 1, &pb, &pe);
+       kg_del_v_g(g, 20);
+       kg_print_g(g);
+       kg_destroy_g(g);
+       return 0;
+}