a) (5 points) Modify the chained hash table from the book (chtbl.h and chtbl.c) so that it auto-grows when its load factor exceeds a given value. (Auto-growing means increasing the number of buckets...

1 answer below »
Please see the Homework.rtf assignment file. The .c and .h files required for completing this assignment are also attached.


a) (5 points) Modify the chained hash table from the book (chtbl.h and chtbl.c) so that it auto-grows when its load factor exceeds a given value. (Auto-growing means increasing the number of buckets in the hash table then rehashing the existing elements.) Begin by modifying the chtbl_init function from the book to have the following prototype: int chtbl_init(CHTbl *htbl, int buckets, int (*h)(const void *key), int (*match)(const void *key1, const void *key2), void (*destroy)(void *data), double maxLoadFactor, double resizeMultiplier); The htbl, buckets, h, match, and destroy parameters have the same meaning as defined in the book. The maxLoadFactor parameter is the maximum load factor the hash table should be allowed to reach before being auto-resized. The resizeMultiplier parameter is the amount by which the number of buckets should be multiplied when a resize occurs (this value must be greater than 1). The maxLoadFactor and resizeMultiplier values should be stored in new fields in the CHTbl struct. Next, modify the code in the chtbl_insert function as follows: 1. Resize the hash table when the load factor exceeds the maximum load factor. The new size of the hash table should be the old size times the resizeMultiplier. All elements currently in the hash table must be rehashed and placed into new buckets. 2. Change the method by which hash codes are mapped to buckets to use the multiplication method instead of the division method. Modify any other parts of CHTbl as needed. Note that removing items from the hash table should not cause the number of buckets in the table to shrink. b) (3 points) Implement a program that demonstrates inserts and lookups with an auto-resizing hash table. This program should initialize the hash table to a small number of buckets then begin inserting integers until a resize occurs. After each insert the program should output the following information: · Number of buckets in the table · Number of elements in the table · The table’s load factor · The table’s max load factor · The table’s resize multiplier For example, if the hash table was initialized to start with 5 buckets, a max load factor of 0.5, and a resize multiplier of 2.0, the following output should be displayed as elements are inserted: buckets 5, elements 1, lf 0.20, max lf 0.5, resize multiplier 2.0 buckets 5, elements 2, lf 0.40, max lf 0.5, resize multiplier 2.0 buckets 10, elements 3, lf 0.33, max lf 0.5, resize multiplier 2.0 Note that in the 3rd line of output the number of buckets has doubled. This happened because the load factor that would result from inserting the 3rd element would have caused the load factor to exceed the max load factor (0.5) so the hash table was auto-resized. After the resize occurs, your program must demonstrate successfully looking up a value that was inserted before the resize and must also demonstrate unsuccessfully looking up a value that does not exist in the table. c) (1 point) Answer the following questions: 1. What is the Big-O execution performance of an insert now that auto-resizing can take place? 2. Why do you think you were required to change chtbl_insert to use the multiplication method instead of the division method to map hash codes to buckets?
Answered Same DayAug 10, 2021

Answer To: a) (5 points) Modify the chained hash table from the book (chtbl.h and chtbl.c) so that it...

Abhishek answered on Aug 12 2021
142 Votes
43140 - C List /Asnwers.txt
1 point) Answer the following questions:
1. What is the Big-O execution performance of an insert now that auto-resizing can take
place?
Ans. When resizing will take place, BIG O will be O(n) or linear
In other conditions, it will remain O(1)
2. Why do you think you were required to change chtbl_insert to use the
multiplication method instead of the division method to map hash codes to buckets?
Ans. The mian advantage of using Multiplication method is that the table size is not critical as earlier in this hashing.
Also, it is more efficient on modern computers, which eliminate floating point arithmetic all together.
43140 - C List /Screenshots/O1.png
43140 - C List /Solution/list.h
/*
* list.h
*/
#ifndef LIST_H
#define LIST_H
#include
/*
* Singly-linked list element
*/
typedef struct ListElmt_
{
void *data;
struct ListElmt_ *next;
} ListElmt;
/*
* Singly-linked list
*/
typedef struct List_
{
int size;
int (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
ListElmt *head;
ListElmt *tail;
} List;
/*
* Public interface
*/
void list_init(List *list, void (*destroy)(void *data));
void list_destroy(List *list);
int list_ins_next(List *list, ListElmt *element, const void *data);
int list_rem_next(List *list, ListElmt *element, void **data);
#define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)
#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next)
#endif
43140 - C List /Solution/list.c
/*****************************************************************************
* *
* -------------------------------- list.c -------------------------------- *
* *
*****************************************************************************/
#include
#include
#include "list.h"
/*****************************************************************************
* *
* ------------------------------- list_init ------------------------------ *
* *
*****************************************************************************/
void list_init(List *list, void (*destroy)(void *data)) {
/*****************************************************************************
* *
* Initialize the list. *
* *
*****************************************************************************/
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
return;
}
/*****************************************************************************
* *
* ----------------------------- list_destroy ----------------------------- *
* *
*****************************************************************************/
void list_destroy(List *list) {
void *data;
/*****************************************************************************
* *
* Remove each element. *
* *
*****************************************************************************/
while (list_size(list) > 0) {
if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy !=
NULL) {
/***********************************************************************
* *
* Call a user-defined function to free dynamically allocated data. *
* *
***********************************************************************/
list->destroy(data);
}
}
/*****************************************************************************
* *
* No operations are allowed now, but clear the structure as a precaution. *
* *
*****************************************************************************/
memset(list, 0, sizeof(List));
return;
}
/*****************************************************************************
* *
* ----------------------------- list_ins_next ---------------------------- *
* *
*****************************************************************************/
int list_ins_next(List *list, ListElmt *element, const void *data) {
ListElmt *new_element;
/*****************************************************************************
* *
* Allocate storage for the element. *
* *
*****************************************************************************/
if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
return -1;
/*****************************************************************************
* *
* Insert the element into the list. *
* *
*****************************************************************************/
new_element->data = (void *)data;
if (element == NULL) {
/**************************************************************************
* *
* Handle insertion at the head of the list. *
* *
**************************************************************************/
if (list_size(list) == 0)
list->tail = new_element;
new_element->next = list->head;
list->head = new_element;
}
else {
/**************************************************************************
* *
* Handle insertion somewhere other than at the head. *
* *
**************************************************************************/
if (element->next == NULL)
list->tail = new_element;
new_element->next = element->next;
element->next = new_element;
}
/*****************************************************************************
* *
* Adjust the size of the list to account for the inserted element. *
* *
*****************************************************************************/
list->size++;
return 0;
}
/*****************************************************************************
* *
* ----------------------------- list_rem_next ---------------------------- *
* ...
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here