enenra
enenra

Reputation: 111

chained hash tables not giving proper output

My current issue is that I have troubles finding the places where my code breaks. I get output, there are no compiling errors, but the output is wrong and incomplete since it looks like it doesn't output everything it should.

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define TABLE_SIZE 8

typedef struct stItem item;
struct stItem {
    int key;
    item *next;
};

void init(item * H[]) {

    int i = 0;
    for (i; i < TABLE_SIZE; i++)
        H[i] = NULL;
}

int h(int k) {

    // this does not work at all (but from exercise description), replaced with temp code

    /*
    int m = TABLE_SIZE;
    int A = ( sqrt(5.0) - 1) / 2;

    return m * (k * A % 1);
    */

    return k % TABLE_SIZE;
}

void insert(int key, item * H[]) {

    int keyHashed = h(key);

    if (H[keyHashed] == NULL) {

        printf("hashkey: %d (%d)\n", keyHashed,key);

        item * temp = malloc(sizeof(item));
        temp->key = key;
        temp->next = NULL;

        H[keyHashed] = temp;

        free(temp);
    }

    else {

        printf("hashkey: %d (%d) (duplicate)\n", keyHashed,key);

        item * temp = malloc(sizeof(item));
        temp->key = NULL;
        temp->next = H[keyHashed]->next;

        while (temp->key != NULL) {
            temp = temp->next;
        }

        temp->key = key;
        temp->next = NULL;
    }
}

int search(int key, item * H[]) {

        int keyHashed = h(key);

        if (H[keyHashed] == NULL)
            return -1;

        else if (H[keyHashed]->key != key) {

            item * temp = malloc(sizeof(item));
            temp->key = NULL;
            temp->next = H[keyHashed]->next;

            while (temp->key != key && temp != NULL)
                temp = temp->next;

            if (temp->key == key) {
                free(temp);
                return keyHashed;
            }

            else {
                free(temp);
                return -1;
            }
        }

        else
            return keyHashed;
}

void printHash(item * H[]) {

    printf("\nTable size: %d\n", TABLE_SIZE);

    int i = 0;

    for (i; i < TABLE_SIZE; i++) {

        if (H[i] != NULL) {
            printf("i: %d          key: %d",i,H[i]->key);

            if (H[i]->next != NULL) {

                printf("chaining print\n");

                item * temp = malloc(sizeof(item));
                temp->key = NULL;
                temp->next = H[i]->next;

                while (temp->key != NULL) {
                    printf(" -> %d", temp->key);
                }

                printf("\n");
            }

            else
                printf("\n");
        }

        else
            printf("i: %d          key: none\n",i);
    }
}

void test() {

    // a)
    int array[7] = {111,10112,1113,5568,63,1342,21231};

    item *h[TABLE_SIZE];
    init(h);

    int i = 0;
    for (i; i < 7; i++)
        insert(array[i], h);

    // b)
    printHash(h);

    // c)
    printf("Search result for 1: %d", search(1, h));
    printf("Search result for 10112: %d", search(10112, h));
    printf("Search result for 1113: %d", search(1113, h));
    printf("Search result for 5568: %d", search(5568, h));
    printf("Search result for 337: %d", search(337, h));
}

int main() {
    test();
}

And here is the current output:

hashkey: 7 (111)
hashkey: 0 (10112)
hashkey: 1 (1113)
hashkey: 0 (5568) (duplicate)
hashkey: 7 (63) (duplicate)
hashkey: 6 (1342)
hashkey: 7 (21231) (duplicate)

Table size: 8
i: 0          key: 5568
i: 1          key: 5568
i: 2          key: none
i: 3          key: none
i: 4          key: none
i: 5          key: none
i: 6          key: 21231
i: 7          key: 5568

Process returned -1073741819 (0xC0000005)   execution time : 0.572 s
Press any key to continue.

As you can see, the search results aren't displayed at all and the hash table is not at all correct. There seem to be numbers where they shouldn't be according to the output and it's not outputting any of the duplicates in the same index at all.

EDIT: The current state of the insert()function:

void insert(int key, item * H[]) {

    int keyHashed = h(key);

    if (H[keyHashed] == NULL) {

        printf("hashkey: %d (%d)\n", keyHashed,key);

        item * temp = malloc(sizeof(item));
        temp->key = key;
        temp->next = NULL;

        H[keyHashed] = temp;
    }

    else {

        printf("hashkey: %d (%d) (duplicate)\n", keyHashed,key);

        item * temp = malloc(sizeof(item));
        temp->key = NULL;
        temp->next = H[keyHashed]->next;

        while (temp->next != NULL) {
            temp = temp->next;
        }

        item * temp2 = malloc(sizeof(item));
        temp->next = temp2;
        temp2->key = key;
        temp2->next = NULL;
    }
}

Upvotes: 0

Views: 40

Answers (1)

Philipp
Philipp

Reputation: 69743

Your problem might be that you free(temp); after inserting it into H. When you insert it, you aren't inserting a copy of the temporary entry, you are inserting a pointer to it. When you then free the memory that pointer points to, it can get overwritten by any later memory allocation.

Yes, the manual memory management in C is a pain.

And then you might want to look at your handling of duplicates again. You are creating a new entry and set it up, but you are never actually entering that entry into H so duplicates are ignored.

Upvotes: 2

Related Questions