AfanasevGad7

This is a task for our favourite professor
git clone git://git.stellar-nexus.ru/AfanasevGad7
Log | Files | Refs | README

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 }