示例#1
0
int merge_left (PBTREE btree, int node_idx, int parent_index_this) {
// copy all elements from this node into the left sibling, along with the
// element in the parent node vector that has this node as its subtree.
// this node and its parent element are then deleted.
    int i;
    int parent_node_idx = btree->nodes[node_idx].parent_node_idx;
    BTREE_ELEMENT parent_elem;
    memcpy(&parent_elem, &btree->nodes[parent_node_idx].elements[parent_index_this], sizeof(BTREE_ELEMENT));
    int left_sib = btree->nodes[parent_node_idx].elements[parent_index_this-1].subtree_node_idx;
    parent_elem.subtree_node_idx = btree->nodes[node_idx].elements[0].subtree_node_idx;
    vector_insert (btree, left_sib, &parent_elem);
    for (i=1; i<btree->nodes[node_idx].element_count; i++)
        vector_insert (btree, left_sib, &btree->nodes[node_idx].elements[i]);
    vector_delete_pos (btree, parent_node_idx, parent_index_this);
    if (parent_node_idx==find_root(btree) && !key_count(btree, parent_node_idx)) {
        set_root(btree, left_sib);
        delete_node(btree, parent_node_idx);
        btree->nodes[left_sib].parent_node_idx = BTREE_INVALID_NODE_IDX;
        delete_node(btree, node_idx);
        return BTREE_INVALID_NODE_IDX;
    }
    else if (parent_node_idx==find_root(btree) && key_count(btree, parent_node_idx)) {
        delete_node(btree, node_idx);
        return BTREE_INVALID_NODE_IDX;
    }
    delete_node(btree, node_idx);
    if (key_count(btree, parent_node_idx) >= btree_minimum_keys())
        return BTREE_INVALID_NODE_IDX; // no need for parent to import an element
    return parent_node_idx; // parent must import an element
}
示例#2
0
int btree_delete_ex (PBTREE btree, int node_idx, long target_key) {
// target is just a package for the key value.  the reference does not
// provide the address of the Elem instance to be deleted.

    // first find the node contain the Elem instance with the given key
    int parent_index_this = BTREE_INVALID_ELEMENT_IDX;
    PBTREE_ELEMENT found;
    int last_visted_node_idx;
    if (node_idx == BTREE_INVALID_NODE_IDX)
        node_idx = btree->root_node_idx;
    last_visted_node_idx = node_idx;
    found = btree_search_ex (btree, &last_visted_node_idx, target_key);
    if (!found)
        return 0;

    if (is_leaf(btree, last_visted_node_idx) && key_count(btree, last_visted_node_idx) > btree_minimum_keys())
        return vector_delete (btree, last_visted_node_idx, target_key);
    else if (is_leaf(btree, last_visted_node_idx)) {
        vector_delete (btree, last_visted_node_idx, target_key);
        // loop invariant: if _node_ is not null_ptr, it points to a node
        // that has lost an element and needs to import one from a sibling
        // or merge with a sibling and import one from its parent.
        // after an iteration of the loop, _node_ may become null or
        // it may point to its parent if an element was imported from the
        // parent and this caused the parent to fall below the minimum
        // element count.
        while (BTREE_IS_VALID_NODE_IDX(last_visted_node_idx)) {
            int right, left;
            // NOTE: the "this" pointer may no longer be valid after the first
            // iteration of this loop!!!
            if (last_visted_node_idx == find_root(btree) && is_leaf(btree, last_visted_node_idx))
                break;
            if (last_visted_node_idx == find_root(btree) && !is_leaf(btree, last_visted_node_idx)) // sanity check
                return 0;
            // is an extra element available from the right sibling (if any)
            right = right_sibling(btree, last_visted_node_idx, &parent_index_this);
            if (BTREE_IS_VALID_NODE_IDX(right) && key_count(btree, right) > btree_minimum_keys())
                last_visted_node_idx = rotate_from_right(btree, last_visted_node_idx, parent_index_this);
            else {
                // is an extra element available from the left sibling (if any)
                left = left_sibling(btree, last_visted_node_idx, &parent_index_this);
                if (BTREE_IS_VALID_NODE_IDX(left) && key_count(btree, left) > btree_minimum_keys())
                    last_visted_node_idx = rotate_from_left(btree, last_visted_node_idx, parent_index_this);
                else if (BTREE_IS_VALID_NODE_IDX(right))
                    last_visted_node_idx = merge_right(btree, last_visted_node_idx, parent_index_this);
                else if (BTREE_IS_VALID_NODE_IDX(left))
                    last_visted_node_idx = merge_left(btree, last_visted_node_idx, parent_index_this);
            }
        }
    }
    else {
        PBTREE_ELEMENT smallest_in_subtree = smallest_key_in_subtree(btree, found->subtree_node_idx);
        found->key = smallest_in_subtree->key;
        found->data_entry_idx = smallest_in_subtree->data_entry_idx;
        btree_delete_ex (btree, found->subtree_node_idx, smallest_in_subtree->key);
    }
    return 1;
}
示例#3
0
int main(int argc, char* argv[])
{
  Table t;

  /* Initialize the table */
  init_table(&t);

  /* Insert into the table */
  test_assert(key_count(&t) == 0, "insert", 0);
  test_assert(!insert(&t, "202", "DC"), "insert", 1);
  test_assert(!insert(&t, "301", "W_MD"), "insert", 2);
  test_assert(key_count(&t) == 2, "insert", 3);

  return 0;
}
示例#4
0
int main(int argc, char* argv[])
{
  Table t;

  /* Initialize the table */
  init_table(&t);

  /* Insert into the table */
  test_assert(key_count(&t) == 0, "insert", 0);
  test_assert(!insert(&t, "202", "DC"), "insert", 1);
  test_assert(key_count(&t) == 1, "insert", 2);

  /* Delete from the table */
  test_assert(!delete(&t, "202"), "delete", 3);
  test_assert(key_count(&t) == 0, "delete", 4);

  return 0;
}
示例#5
0
文件: secret07.c 项目: Foshie/Classes
int main(int argc, char* argv[])
{
  Table t;
  char str[10];

  /* Initialize the table */
  init_table(&t);

  /* Search for non-existent entries */
  test_assert(key_count(&t) == 0, "key_count", 0);
  test_assert(!insert(&t, "Jack", "2278"), "insert", 1);
  test_assert(!insert(&t, "Mike", "2056"), "insert", 2);
  test_assert(key_count(&t) == 2, "key_count", 3);
  test_assert(search(&t, "Fred", str), "delete", 4);
  test_assert(key_count(&t) == 2, "key_count", 5);
 
  return 0;
}
int main(int argc, char* argv[]){
	int index;
	Table t;
	const char key[26] ={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
	
	init_table(&t);
	for(index = 0; index < 26; index++){
  /* Insert into the table */
  		insert(&t, key[index], "DC");
  	
	}
	test_assert(key_count(&t) == 26, "key_count", 0);
	return 0;
}
示例#7
0
//search for Element have greatest value less than desired...
template<class KEY, class VALUE> Elem& Nde::searchGL(Elem& desired) {
    // the zeroth element of the vector is a special case (no key value or
    // payload, just a subtree).  the seach starts at the *this node, not
    // at the root of the b-tree.
    Nde* current = this;
    if (!key_count()){ current = 0;}

    while (current) {
        // desired less than all values in current node
        if (current->m_count>1 && desired<current->m_vector[1]){
            current = current->m_vector[0].mp_subtree;

        // desired greater than all values in current node
        } else if (desired>current->m_vector[current->m_count-1]){
            if(!current->m_vector[current->m_count-1].mp_subtree)
                //ABOVE ALL LEAVES CASE
                //We're at the end of the sequence
                { return current->m_vector[current->m_count-1]; }
            else {current = current->m_vector[current->m_count-1].mp_subtree;}
        } else {
            // binary search of the node
            int first = 1;
            int last = current->m_count-1;
            while (last-first > 1) {
                int mid = first+(last-first)/2;
                if (desired>=current->m_vector[mid]){ first = mid;}
                else{ last = mid;}
            }
            //Exact MATCH TO LEAF CASES
            if(current->m_vector[first]==desired) {return current->m_vector[first];}
            if(current->m_vector[last]==desired) {return current->m_vector[last];}

            //BETWEEN TWO LEAVES CASE
            //within an interval on level last = first +1 !!
            if(!current->m_vector[first].mp_subtree && !current->m_vector[last].mp_subtree){
                return current->m_vector[first];
            }

            Elem& lGelem = current->m_vector[last].mp_subtree->smallest_key_in_subtree();
            if(desired < lGelem) {
                current = current->m_vector[last].mp_subtree;
            } else {
                current = current->m_vector[first].mp_subtree;
            }
        }
    }

    //BELOW ALL LEAVES CASE
    return m_failure;
}
示例#8
0
PBTREE_ELEMENT btree_search_ex (PBTREE btree, int *node_idx, long desired_key) {
    // the zeroth element of the vector is a special case (no key value or
    // payload, just a subtree).  the seach starts at the *this node, not
    // at the root of the b-tree.
    int current_node_idx = *node_idx;
    if (!key_count(btree, *node_idx))
        current_node_idx = BTREE_INVALID_NODE_IDX;
    while (BTREE_IS_VALID_NODE_IDX(current_node_idx)) {
        *node_idx = current_node_idx;
        // if desired is less than all values in current node
        if (btree->nodes[current_node_idx].element_count>1 && desired_key < btree->nodes[current_node_idx].elements[1].key)
            current_node_idx = btree->nodes[current_node_idx].elements[0].subtree_node_idx;
        // if desired is greater than all values in current node
        else if (desired_key > btree->nodes[current_node_idx].elements[btree->nodes[current_node_idx].element_count-1].key)
            current_node_idx = btree->nodes[current_node_idx].elements[btree->nodes[current_node_idx].element_count-1].subtree_node_idx;
        else {
            // binary search of the node
            int first = 1;
            int last = btree->nodes[current_node_idx].element_count-1;
            while (last-first > 1) {
                int mid = first+(last-first)/2;
                if (desired_key >= btree->nodes[current_node_idx].elements[mid].key)
                    first = mid;
                else
                    last = mid;
            }
            if (btree->nodes[current_node_idx].elements[first].key == desired_key)
                return &btree->nodes[current_node_idx].elements[first];
            if (btree->nodes[current_node_idx].elements[last].key == desired_key)
                return &btree->nodes[current_node_idx].elements[last];
            else if (btree->nodes[current_node_idx].elements[last].key > desired_key)
                current_node_idx = btree->nodes[current_node_idx].elements[first].subtree_node_idx;
            else
                current_node_idx =btree->nodes[current_node_idx].elements[last].subtree_node_idx;
        }
    }

    return NULL;

}
示例#9
0
template<class KEY, class VALUE> Elem& Nde::search (Elem& desired, Nde*& last_visited_ptr) {
    // the zeroth element of the vector is a special case (no key value or
    // payload, just a subtree).  the seach starts at the *this node, not
    // at the root of the b-tree.
    Nde* current = this;
    if (!key_count()){ current = 0;} 
    
    while (current) {
        last_visited_ptr = current;
        // if desired is less than all values in current node
        if (current->m_count>1 && desired<current->m_vector[1])
            current = current->m_vector[0].mp_subtree;
        // if desired is greater than all values in current node
        else if (desired>current->m_vector[current->m_count-1])
            current = current->m_vector[current->m_count-1].mp_subtree;
        else {
            // binary search of the node
            int first = 1;
            int last = current->m_count-1;
            while (last-first > 1) {
                int mid = first+(last-first)/2;
                if (desired>=current->m_vector[mid])
                    first = mid;
                else
                    last = mid;
            }
            if (current->m_vector[first]==desired)
                return current->m_vector[first];
            if (current->m_vector[last]==desired)
                return current->m_vector[last];
            else if (current->m_vector[last]>desired)
                current = current->m_vector[first].mp_subtree;
            else
                current = current->m_vector[last].mp_subtree;
        }
    }
 
    return m_failure;
}
示例#10
0
/**************************************************************
* main takes in a number of arguments, for this project only  *
* 1 or 2 arguments is considered valid. If there is only one  *
* argument, we will treat stdin as the input source. If there *
* are two arguments, we will treat the second argument as a   *
* data file that commands may be read from.                   *
**************************************************************/
int main(int argc, char *argv[]){
	FILE *input;
	char line[MAX_LEN + 1], first_word[MAX_LEN + 1], second_word[MAX_LEN + 1]
	, val[MAX_LEN + 1];
	Table t;
	int index;

	init_table(&t);
	/* If only one argument is present, command line input will be used.*/
	if(argc == 1){
		input = stdin;
		/* IF two arguments are present, the second argument is 
		taken to be a data file.*/
	} else if(argc == 2){
		input = fopen(argv[1], "r");
		/*If the file cannot be opened, an error message will be printed,
		  and the program will exit. */
		if(input == NULL){
			fprintf(stderr, "File %s open failed. Error: %s.\n", argv[1], strerror(errno));
          	exit(EX_OSERR);   
		}
		/*If there are more than two arguments present, an error message 
		will be printed, and the program will exit.*/
	} else{
		fprintf(stderr, "Too many input arguments. Error : %s.\n", strerror(errno));
		exit(EX_USAGE);
	}
	/* As fgets reads in each line of the input, sscanf reads the first 
		word of each line and assigns it to first_word.*/
	while (fgets(line, MAX_LEN + LEN_EXTRA, input) != NULL) {
		/*If a line is too long, an error message is printed out, and the program exits.*/
		if(strlen(line) > MAX_LEN){
			fprintf(stderr, "Line is greater than 1024 characters. Error: %s.\n", strerror(errno));
			exit(EX_DATAERR);
		}
       	 sscanf(line, "%s", first_word);
       	 /*If we have a blank line, we skip it.*/
       	 if(strcmp(line, "\n") == 0){
			continue;
		} 
		/*If the first non-whitespace character is a '#', this line is a comment,
      		and we skip it.*/
		else if(first_word[0] == '#'){
			continue;
			/*If the first word in a line is "insert" and all arguments are present,
			 we attempt to insert a key/value pair*/
		}else if(strcmp(first_word, "insert") == 0 && sscanf(line, "%s %s %s", first_word, second_word, val) == INSERT_ARGS){
				/*If the insertion is successful, we print the success message*/
				if(insert(&t, second_word, val) == 0){
					printf("Insertion of %s => %s succeeded.\n", second_word, val);
					/*Otherwise, we print the failure message.*/
				} else{
					printf("Insertion of %s => %s failed.\n", second_word, val);
				}
			/*If the first word of a line is "search" and both arguments are present,  
			we attempt to search for a key in the table.*/		
		} else if(strcmp(first_word, "search") == 0 && sscanf(line, "%s %s", first_word, second_word) == SEARCH_ARGS){			
				/*If the search succeeds, we print the success message*/
				if(search(&t, second_word, val) == 0){
					printf("Search for %s succeeded (%s).\n", second_word, val);
					/*If the search fails, we print the failure message.*/
				} else{
					printf("Search for %s failed.\n", second_word);
				} 
			/*If the first word in the line is "delete" and both arguments are present, 
				we attempt to delete a key from the table. */
		} else if(strcmp(first_word, "delete") == 0 && sscanf(line, "%s %s", first_word, second_word) == DELETE_ARGS){
				/*If the deletion succeeds, we print out the success message.*/
				if(delete(&t, second_word) == 0){
					printf("Deletion of %s succeeded.\n", second_word);
					/*If the deletion fails, we print out the ffailure message.*/
				} else{
					printf("Deletion of %s failed.\n", second_word);
				}
			/*If the first word in a line is "reset", we attempt to reset the table.*/
		}else if(strcmp(first_word, "reset") == 0){
				/*Reset the table, then print success message.*/
				reset_table(&t);
				printf("Table reset.\n");
			/*If the first word in a line is "display" and both arguments are present, 
				we display either the contents of the table or the key count.*/
		} else if(strcmp(first_word, "display") == 0 && sscanf(line, "%s %s", first_word, second_word) == DISPLAY_ARGS){
				/*If the item to display is key count we attempt to 
					display the key_count.*/
				if(strcmp(second_word, "key_count") == 0){
					/*If key_count succeeds, the key count will be printed,
						otherwise 0 will be printed. */
					if(key_count(&t) != -1){
						printf("Key count: %d\n", key_count(&t));
					} else{
						printf("Key count: 0\n");
					}
					/*If the item to be displayed is the table, we will
					attempt to print out the contents of the table. */
				} else if(strcmp(second_word, "table") == 0){
					/*We iterate through the table and print out the bucket
						number, state, and (if the bucket is full) its key
						and value.*/
					for(index = 0; index < NUM_BUCKETS; index++){
						if(t.buckets[index].state == EMPTY){
							printf("Bucket %d: EMPTY\n", index);
						} else if(t.buckets[index].state == DELETED){
							printf("Bucket %d: DELETED\n", index);
						} else{
							printf("Bucket %d: FULL (%s => %s)\n", index,
								t.buckets[index].data.key, t.buckets[index].data.value);
						}
					}
				}
			/*If an invalid line is found we print out an error message and exit.*/
		} else{
			fprintf(stderr, "Invalid line found, retry with valid command, comment, or empty line. Error: %s.\n", strerror(errno));
			exit(EX_DATAERR);
		}
	}
	/*When we are done, we close the file and return 0.*/
		fclose(input);

		return 0;
}