ntree.cxx (4403B)
1 #include <algorithm> 2 #include <climits> 3 #include <cstdint> 4 #include <iostream> 5 #include <vector> 6 7 extern "C" { 8 #include "tree.h" 9 } 10 11 #include "config.h" 12 13 14 class NTree { 15 16 struct Node { 17 int id, data; 18 std::vector<Node*> children; 19 }; 20 21 22 bool push_node(int id, int data, Node *rt) { 23 Node *n = new Node; 24 25 n->id = id; 26 n->data = data; 27 28 rt->children.push_back(n); 29 30 n = rt->children.back(); 31 32 return true; 33 } 34 35 36 Node* find_parent_node(Node *rt, Node *rt_s) { 37 38 if (rt_s->id == 0) return 0; 39 40 if (rt->children.size() == 0) return 0; 41 42 std::vector<Node*> rts; 43 44 for (Node *c : rt->children) { 45 if (c->id == rt_s->id) return rt; 46 rts.push_back(this->find_parent_node(c, rt_s)); 47 } 48 49 for (Node *i : rts) { 50 if (i) return i; 51 } 52 53 return 0; 54 } 55 56 57 public: 58 59 Node *root = new Node; 60 61 int last_id = 0; 62 63 64 NTree() { 65 Node *genesis = new Node; 66 67 genesis->id = 0; 68 genesis->data = 0; 69 70 this->root = genesis; 71 } 72 73 74 bool insert(int parent_id, int data, Node *rt) { 75 76 if (rt->id == parent_id) return this->push_node(++this->last_id, data, rt); 77 78 if (rt->children.size() == 0) return false; 79 80 std::vector<bool> r; 81 82 for (auto c : rt->children) { 83 r.push_back(this->insert(parent_id, data, c)); 84 } 85 86 for (bool a : r) { 87 if (a) return true; 88 } 89 90 return false; 91 }; 92 93 94 void parse(Node *rt) { 95 Node *p = this->find_parent_node(this->root, rt); 96 std::cout << std::endl << "id: " << rt->id << " data: " << rt->data << " parent id: " << (p ? p->id : (rt->id ? -1 : 0)); 97 98 for (Node *c : rt->children) { 99 this->parse(c); 100 } 101 } 102 103 104 Node* search(int id, Node *rt) { 105 106 if (rt->id == id) return rt; 107 108 std::vector<Node*> r; 109 110 for (Node *c : rt->children) { 111 r.push_back(this->search(id, c)); 112 } 113 114 for (Node *c : r) { 115 if (c) return c; 116 } 117 118 return 0; 119 } 120 121 122 bool remove(int id) { 123 Node *n = this->search(id, this->root); 124 if (!n) return false; 125 126 Node *n_p = this->find_parent_node(this->root, n); 127 if (!n_p) return false; 128 129 for (Node *r : n->children) n_p->children.push_back(r); 130 131 auto it = std::find(n_p->children.begin(), n_p->children.end(), n); 132 if (it != n_p->children.end()) 133 n_p->children.erase(it); 134 135 delete n; 136 137 return true; 138 139 } 140 }; 141 142 static void 143 usage(void) 144 { 145 eprintf("usage: %s [-c] [-s] [-d] [filename]\n", argv0); 146 } 147 148 int 149 main(int argc, char *argv[]) 150 { 151 int cflag = 0, sflag = 0, dflag = 0; 152 ARGBEGIN { 153 case 'c': 154 cflag = 1; 155 break; 156 case 's': 157 sflag = 1; 158 break; 159 case 'd': 160 dflag = 1; 161 break; 162 } ARGEND 163 if (argc > 1 || (cflag + sflag + dflag) < 1) 164 usage(); 165 const char *filename; 166 if (argc == 1) 167 filename = argv[0]; 168 else 169 filename = FILENAME; 170 171 FILE *file; 172 if (!(file = fopen(filename, "r"))) 173 eprintf("fopen %s:", filename); 174 175 int arr[TESTNUMBER+1], ch; 176 char w[64]; 177 int len = 0, wi = 0; 178 do { 179 ch = fgetc(file); 180 if (!isspace(ch) && ch != EOF) { 181 w[wi++] = ch; 182 } else if (wi > 0) { 183 w[wi] = '\0'; 184 arr[len++] = estrtonum(w, 0, INT_MAX); 185 wi = 0; 186 } 187 } while (ch != EOF && len <= TESTNUMBER); 188 efshut(file, filename); 189 if (len < TESTNUMBER) 190 eprintf("Array too small\n"); 191 if (len > TESTNUMBER) 192 weprintf("Array too big - using only the first %d elements\n", TESTNUMBER); 193 194 NTree r; 195 clock_t start_time, elapsed = 0; 196 197 if (cflag) 198 start_time = clock(); 199 for (int i = 0; i < TESTNUMBER; ++i) 200 r.insert(arr[i] % (i+1), arr[i], r.root); 201 if (cflag) 202 elapsed += clock() - start_time; 203 204 volatile uintptr_t checksum = 0; /* to avoid optimization */ 205 if (sflag) { 206 start_time = clock(); 207 for (int i = 0; i < TESTNUMBER; ++i) 208 checksum = (uintptr_t)r.search(arr[i] % (i+1), r.root); 209 elapsed += clock() - start_time; 210 } 211 212 if (dflag) { 213 start_time = clock(); 214 for (int i = 0; i < TESTNUMBER; ++i) 215 r.remove(arr[i] % (i+1)); 216 elapsed += clock() - start_time; 217 } 218 219 printf("%f\n", (double)elapsed/CLOCKS_PER_SEC); 220 }