/*Gets the line of number index, if such a line exists, and returns NULL else*/ char * get_line(text_t *txt, int index){ if(txt==NULL){ return NULL; }else{ if(index==0){ return NULL; } if(index==length_text(txt)+1){ return NULL; } if(index>length_text(txt)+1){ //printf("-"); return NULL; } while(txt->right!=NULL){ if(index<=txt->key){ txt=txt->left; }else if(index>txt->key){ index=index-txt->key; txt=txt->right; } } return (char*)txt->left; } }
/* Appends new line as new last line */ void append_line(text_t *txt, char * new_line){ if(txt==NULL){ //No tree return NULL; }else{ //Get total lines and insert as last line int total_line=length_text(txt); insert_line(txt,total_line+1,new_line); } }
void append_line(text_t *txt,char *new_line) { tree_node_t *root_node; root_node = txt->searchtree; if (root_node->left == NULL) { list_t *string_element; string_element = get_string(); string_element->data = strdup(new_line); root_node->key = 1; root_node->left = (tree_node_t *) string_element; root_node->right = NULL; root_node->height = 0; } else { insert_line(txt,length_text(txt) + 1,new_line); } }
int main(){ int i, tmp; tree_node *txt1, *txt2, *txt3; char *c; printf("starting \n"); txt1 = create_text(); txt2 = create_text(); txt3 = create_text(); append_line(txt1, "line one" ); if( (tmp = length_text(txt1)) != 1) { printf("Test 1: length should be 1, is %d\n", tmp); exit(-1); } append_line(txt1, "line hundred" ); insert_line(txt1, 2, "line ninetynine" ); insert_line(txt1, 2, "line ninetyeight" ); insert_line(txt1, 2, "line ninetyseven" ); insert_line(txt1, 2, "line ninetysix" ); insert_line(txt1, 2, "line ninetyfive" ); for( i = 2; i <95; i++ ) insert_line(txt1, 2, "some filler line between 1 and 95" ); if( (tmp = length_text(txt1)) != 100) { printf("Test 2: length should be 100, is %d\n", tmp); exit(-1); } printf("found at line 1: %s\n",get_line(txt1, 1)); printf("found at line 2: %s\n",get_line(txt1, 2)); printf("found at line 99: %s\n",get_line(txt1, 99)); printf("found at line 100: %s\n",get_line(txt1,100)); for(i=1; i<=10000; i++) { if( i%2==1 ) append_line(txt2, "A"); else append_line(txt2, "B"); } if( (tmp = length_text(txt2)) != 10000) { printf("Test 3: length should be 10000, is %d\n", tmp); exit(-1); } c = get_line(txt2, 9876 ); if( *c != 'B') { printf("Test 4: line 9876 of txt2 should be B, found %s\n", c); exit(-1); } for( i= 10000; i > 1; i-=2 ) { c = delete_line(txt2, i); if( *c != 'B') { printf("Test 5: line %d of txt2 should be B, found %s\n", i, c); exit(-1); } append_line( txt2, c ); } for( i=1; i<= 5000; i++ ) { c = get_line(txt2, i); if( *c != 'A') { printf("Test 6: line %d of txt2 should be A, found %s\n", i, c); exit(-1); } } for( i=1; i<= 5000; i++ ) delete_line(txt2, 1 ); for( i=1; i<= 5000; i++ ) { c = get_line(txt2, i); if( *c != 'B') { printf("Test 7: line %d of txt2 should be B, found %s\n", i, c); exit(-1); } } set_line(txt1, 100, "the last line"); for( i=99; i>=1; i-- ) delete_line(txt1, i ); printf("found at the last line: %s\n",get_line(txt1, 1)); for(i=0; i<1000000; i++) append_line(txt3, "line" ); if( (tmp = length_text(txt3)) != 1000000) { printf("Test 8: length should be 1000000, is %d\n", tmp); exit(-1); } for(i=0; i<500000; i++) delete_line(txt3, 400000 ); if( (tmp = length_text(txt3)) != 500000) { printf("Test 9: length should be 500000, is %d\n", tmp); exit(-1); } printf("End of tests\n"); return 0; }
/* This function deletes the line of number index, renumbering all lines after that line, and returns a pointer to the deleted line */ char * delete_line(text_t *txt, int index) { text_t *tmp_node, *upper_node, *other_node; object_t *deleted_object; int count = index; int finished; tmp_node = txt; if (txt->left == NULL || length_text(txt) < index) { return NULL; } else if (txt->right == NULL) { deleted_object = (object_t *)txt->left; txt->left = NULL; txt->parent = NULL; txt->key = -1; txt->height = -1; return (deleted_object); } else { while(tmp_node->right != NULL) { upper_node = tmp_node; (tmp_node->key)--; if (count <= tmp_node->left->key) { tmp_node = tmp_node->left; tmp_node = upper_node->left; other_node = upper_node->right; } else { count -= tmp_node->left->key; tmp_node = tmp_node->right; tmp_node = upper_node->right; other_node = upper_node->left; } } upper_node->key = other_node->key; upper_node->left = other_node->left; upper_node->right = other_node->right; upper_node->height = other_node->height; if (upper_node->right != NULL) { upper_node->left->parent = upper_node; upper_node->right->parent = upper_node; } deleted_object = (object_t *) tmp_node->left; return_node(tmp_node); return_node(other_node); upper_node = upper_node->parent; tmp_node = upper_node; finished = 0; while(!finished && tmp_node!=NULL) { int tmp_height, old_height; old_height = tmp_node->height; if (tmp_node->left->height - tmp_node->right->height == 2) { if (tmp_node->left->left->height - tmp_node->right->height == 1) { right_rotation(tmp_node); tmp_node->right->height = tmp_node->right->left->height + 1; tmp_node->height = tmp_node->right->height + 1; tmp_node->right->key = tmp_node->right->left->key + tmp_node->right->right->key; tmp_node->key = tmp_node->left->key + tmp_node->right->key; } else { left_rotation(tmp_node->left); right_rotation(tmp_node); tmp_height = tmp_node->left->left->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; tmp_node->left->key = tmp_node->left->left->key + tmp_node->left->right->key; tmp_node->right->key = tmp_node->right->left->key + tmp_node->right->right->key; tmp_node->key = tmp_node->left->key + tmp_node->right->key; } } else if (tmp_node->left->height - tmp_node->right->height == -2) { if( tmp_node->right->right->height - tmp_node->left->height == 1) { left_rotation(tmp_node); tmp_node->left->height = tmp_node->left->right->height + 1; tmp_node->height = tmp_node->left->height + 1; tmp_node->left->key = tmp_node->left->left->key + tmp_node->left->right->key; tmp_node->key = tmp_node->left->key + tmp_node->right->key; } else { right_rotation(tmp_node->right); left_rotation(tmp_node); tmp_height = tmp_node->right->right->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; tmp_node->right->key = tmp_node->right->left->key + tmp_node->right->right->key; tmp_node->left->key = tmp_node->left->left->key + tmp_node->left->right->key; tmp_node->key = tmp_node->left->key + tmp_node->right->key; } } else { if(tmp_node->left->height > tmp_node->right->height) { tmp_node->height = tmp_node->left->height + 1; } else { tmp_node->height = tmp_node->right->height + 1; } } if (tmp_node->height == old_height) { finished = 1; } tmp_node = tmp_node->parent; } return (deleted_object); } }
/* Deletes the line of number index, renumbering all lines after that line, and returns a pointer to the deleted line */ char * delete_line(text_t *txt, int index){ text_t * init_text=txt; if(txt==NULL){ //No Tree return NULL; }else{ int length=length_text(txt); //Check index with maxlength if(index>length){ return NULL; }else{ //Initialize stack createstack(); text_t * uppernode; text_t * sel_node; text_t * other_node; while(txt->right!=NULL){ push(txt); uppernode=txt; if(index<=txt->key){ sel_node=txt->left; other_node=txt->right; txt->key=txt->key-1; txt=txt->left; }else{ index=index-txt->key; sel_node=txt->right; other_node=txt->left; txt=txt->right; } } //Pop the last node pop(); uppernode->left=other_node->left; uppernode->right=other_node->right; uppernode->key=other_node->key; uppernode->height=other_node->height; text_t * tmp_node=NULL; int finished=0; while( !stack_empty() && !finished ){ int tmp_height, old_height; tmp_node = pop(); old_height= tmp_node->height; if( tmp_node->left->height - tmp_node->right->height == 2 ) { if( tmp_node->left->left->height - tmp_node->right->height == 1 ) { right_rotation( tmp_node ); tmp_node->right->height = tmp_node->right->left->height + 1; tmp_node->height = tmp_node->right->height + 1; } else { left_rotation( tmp_node->left ); right_rotation( tmp_node ); tmp_height = tmp_node->left->left->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; } }else if( tmp_node->left->height - tmp_node->right->height == -2 ) { if( tmp_node->right->right->height - tmp_node->left->height == 1 ) { left_rotation( tmp_node ); tmp_node->left->height =tmp_node->left->right->height + 1; tmp_node->height = tmp_node->left->height + 1; } else { right_rotation( tmp_node->right ); left_rotation( tmp_node ); tmp_height = tmp_node->right->right->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; } } else /* update height even if there was no rotation */ { if( tmp_node->left->height > tmp_node->right->height ) tmp_node->height = tmp_node->left->height + 1; else tmp_node->height = tmp_node->right->height + 1; } if( tmp_node->height == old_height ) finished = 1; } remove_stack(); return (char *)sel_node->left; /* if(index-txt->key==1){ }else{ //Node not found printf("shouldn't come here"); }*/ } } }
/* Inserts the line before the line of number index, if such a line exists, to new line, renumbering all lines after that line. If no such line exists, it appends new line as new last line */ void insert_line(text_t *txt, int index, char * new_line) { if(txt==NULL){ //printf("Should not come here"); return NULL; }else if( txt->left == NULL ) { if(index>length_text(txt)+1){ index=length_text(txt)+1; } txt->left = (struct text_t *) new_line; txt->key = 0; txt->height = 0; txt->right = NULL; }else{ //check max line if(index>length_text(txt)+1){ index=length_text(txt)+1; } createstack(); while(txt->right!=NULL){ push(txt); if(index<=txt->key){ txt->key=txt->key+1; txt=txt->left; }else if(index>txt->key){ index=index-txt->key; txt=txt->right; } } //create a new Node text_t * old_node=malloc(sizeof(text_t)); old_node->key=0; old_node->left=txt->left; old_node->right=txt->right; old_node->height=0; text_t * new_node=malloc(sizeof(text_t)); new_node->key=0; new_node->left=(struct text_t *)new_line; new_node->right=NULL; new_node->height=0; if(index-txt->key==0){ txt->left=new_node; txt->right=old_node; txt->height=height(txt); }else if(index-txt->key==1){ txt->left=new_node; txt->right=old_node; txt->height=height(txt); }else{ txt->left=old_node; txt->right=new_node; txt->height=height(txt); } txt->key=1; //balance the tree //Need stack text_t * tmp_node=NULL; int finished =0; while( !stack_empty() && !finished ){ int tmp_height, old_height; tmp_node = pop(); old_height= tmp_node->height; if( tmp_node->left->height - tmp_node->right->height == 2 ) { if( tmp_node->left->left->height - tmp_node->right->height == 1 ) { right_rotation( tmp_node ); tmp_node->right->height = tmp_node->right->left->height + 1; tmp_node->height = tmp_node->right->height + 1; } else { left_rotation( tmp_node->left ); right_rotation( tmp_node ); tmp_height = tmp_node->left->left->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; } }else if( tmp_node->left->height - tmp_node->right->height == -2 ) { if( tmp_node->right->right->height - tmp_node->left->height == 1 ) { left_rotation( tmp_node ); tmp_node->left->height =tmp_node->left->right->height + 1; tmp_node->height = tmp_node->left->height + 1; } else { right_rotation( tmp_node->right ); left_rotation( tmp_node ); tmp_height = tmp_node->right->right->height; tmp_node->left->height = tmp_height + 1; tmp_node->right->height = tmp_height + 1; tmp_node->height = tmp_height + 2; } } else /* update height even if there was no rotation */ { if( tmp_node->left->height > tmp_node->right->height ) tmp_node->height = tmp_node->left->height + 1; else tmp_node->height = tmp_node->right->height + 1; } if( tmp_node->height == old_height ) finished = 1; } remove_stack(); } }
void append_line( text_t *txt, char *new_line ) { insert_line( txt, length_text( txt ) + 1, new_line ); }