//returns the total number of collided cells int add_block_1_axis(rb_red_blk_tree *tree, int x1, int y1, int x2, int y2, unsigned int type, int add_amount) { circ_tree_node *node_begin, *node_end; node_end = get_node(tree, x2, type)->key; //the end strictly needs to be called before the beginning node_begin = get_node(tree, x1, type)->key; stk_stack *axis_range = RBEnumerate(tree, node_begin, node_end); rb_red_blk_node *rb_node, *rb_node_prev = NULL; int temp_collision = 0, collision = 0, prev_pos; for (;;) { //rb_node_prev = rb_node; rb_node = (rb_red_blk_node *) StackPop(axis_range); //if (rb_node_prev == NULL) rb_node_prev = TreePredecessor(tree, rb_node); circ_tree_node *node = (circ_tree_node *) rb_node->key; circ_tree_node *node_prev; if (rb_node_prev == NULL || rb_node_prev == tree->nil) node_prev = NULL; else node_prev = (circ_tree_node *) rb_node_prev->key; unsigned int stack_not_empty = StackNotEmpty(axis_range); //collision if (temp_collision) //if temp collision is non-zero, by definition, node_prev //cannot be NULL collision += temp_collision * (node->pos - prev_pos); prev_pos = node->pos; if (type == TOP_LEVEL) { if (stack_not_empty) temp_collision = add_block_1_axis(node->data.tree, y1, 0, y2, 0, SECOND_LEVEL, add_amount); if ((node_prev != NULL && !RBTreeCompare(node->data.tree, node_prev->data.tree, circ_node_equals)) || (node_prev == NULL && RBIsTreeEmpty(node->data.tree))) RBDelete(tree, rb_node); } else { if (stack_not_empty) { if (node->data.state > 0 && node->data.state > -add_amount) //if there is already a block here, and if there would still //be a block left, assess collision temp_collision = add_amount; else temp_collision = 0; node->data.state += add_amount; } //if both nodes are the same if ((node_prev != NULL && node_prev->data.state == node->data.state) || //or the previous node is null and this is zero (node_prev == NULL && node->data.state == 0)) { RBDelete(tree, rb_node); } } if (!stack_not_empty) break; } StackDestroy(axis_range, dummy_fun); return collision; }
//prints x by x view of the tree //assumes the grid starts from 0, 0; if there are entries less //than that, it will be ignored, possibly to yield weird results void print_tree(circ_tree *c_tree, int x, unsigned int print_mode) { rb_red_blk_tree *tree = c_tree->main_tree; static int static_x = 0; static circ_tree_node query_node_low, query_node_high; static char *line, *header_line; if (static_x != x) { if (line != NULL) free(line); if (header_line != NULL) free(header_line); static_x = x; query_node_low.pos = 0; //start node query_node_high.pos = x; int size = sizeof(char) * (x + 3); line = (char *) malloc(size); header_line = (char *) malloc(size); header_line[0] = ' '; header_line[1] = ' '; int i; for (i = 0; i < x; i++) header_line[2 + i] = '0' + (i % 10); header_line[x + 2] = '\0'; } line[1] = ' '; memset(line + 2, print_mode == PRINT_CELLS ? '0' : ' ', x); //initial line is all zeros line[x + 2] = '\0'; //null char at the end stk_stack *stack = RBEnumerate(tree, &query_node_low, &query_node_high); int line_n = 0; puts(header_line); int cont_print = 1; while (cont_print) { int node_pos; rb_red_blk_tree *node_tree; if (cont_print = StackNotEmpty(stack)) { circ_tree_node *node = ((rb_red_blk_node *) StackPop(stack))->key; node_pos = node->pos; node_tree = node->data.tree; } else { node_pos = x; node_tree = c_tree->y_bound_tree; } for (; line_n < node_pos; line_n++) { //print the lines until this point / rest of the lines line[0] = '0' + (line_n % 10); puts(line); } //set the new line stk_stack *stack2 = RBEnumerate(node_tree, &query_node_low, &query_node_high); char c = print_mode == PRINT_CELLS ? '0' : ' '; int row_n = 0; while (StackNotEmpty(stack2)) { circ_tree_node *node2 = ((rb_red_blk_node *) StackPop(stack2))->key; for (; row_n < node2->pos; row_n++) //print the chars until this point line[row_n + 2] = c; if (print_mode == PRINT_CELLS) c = '0' + node2->data.state; else line[row_n++ + 2] = '0' + node2->data.state; } if (print_mode == PRINT_NODES && row_n == 0) line[1] = '0'; for (; row_n < x; row_n++) //print the rest of the chars line[row_n + 2] = c; free(stack2); if (print_mode == PRINT_NODES || !cont_print) { if (cont_print) line[0] = '0' + (line_n++ % 10); else line[0] = '>'; //print a different indicator for the boundary tree puts(line); memset(line + 1, ' ', x + 1); } } free(stack); }
int main() { stk_stack* enumResult; int option=0; int newKey,newKey2; int* newInt; rb_red_blk_node* newNode; rb_red_blk_tree* tree; tree=RBTreeCreate(IntComp,IntDest,InfoDest,IntPrint,InfoPrint); while(option!=8) { printf("choose one of the following:\n"); printf("(1) add to tree\n(2) delete from tree\n(3) query\n"); printf("(4) find predecessor\n(5) find sucessor\n(6) enumerate\n"); printf("(7) print tree\n(8) quit\n"); do option=fgetc(stdin); while(-1 != option && isspace(option)); option-='0'; switch(option) { case 1: { printf("type key for new node\n"); scanf("%i",&newKey); newInt=(int*) malloc(sizeof(int)); *newInt=newKey; RBTreeInsert(tree,newInt,0); } break; case 2: { printf("type key of node to remove\n"); scanf("%i",&newKey); if ( ( newNode=RBExactQuery(tree,&newKey ) ) ) RBDelete(tree,newNode);/*assignment*/ else printf("key not found in tree, no action taken\n"); } break; case 3: { printf("type key of node to query for\n"); scanf("%i",&newKey); if ( ( newNode = RBExactQuery(tree,&newKey) ) ) {/*assignment*/ printf("data found in tree at location %i\n",(int)newNode); } else { printf("data not in tree\n"); } } break; case 4: { printf("type key of node to find predecessor of\n"); scanf("%i",&newKey); if ( ( newNode = RBExactQuery(tree,&newKey) ) ) {/*assignment*/ newNode=TreePredecessor(tree,newNode); if(tree->nil == newNode) { printf("there is no predecessor for that node (it is a minimum)\n"); } else { printf("predecessor has key %i\n",*(int*)newNode->key); } } else { printf("data not in tree\n"); } } break; case 5: { printf("type key of node to find successor of\n"); scanf("%i",&newKey); if ( (newNode = RBExactQuery(tree,&newKey) ) ) { newNode=TreeSuccessor(tree,newNode); if(tree->nil == newNode) { printf("there is no successor for that node (it is a maximum)\n"); } else { printf("successor has key %i\n",*(int*)newNode->key); } } else { printf("data not in tree\n"); } } break; case 6: { printf("type low and high keys to see all keys between them\n"); scanf("%i %i",&newKey,&newKey2); enumResult=RBEnumerate(tree,&newKey,&newKey2); while ( (newNode = StackPop(enumResult)) ) { tree->PrintKey(newNode->key); printf("\n"); } free(enumResult); } break; case 7: { RBTreePrint(tree); } break; case 8: { RBTreeDestroy(tree); return 0; } break; default: printf("Invalid input; Please try again.\n"); } } return 0; }