【问题标题】:Hashtable & BST Implementation哈希表和 BST 实现
【发布时间】:2018-01-06 08:08:54
【问题描述】:

我正在处理一项可以接受来自键盘的命令以将人员插入哈希表的任务。将某人插入 hastable 后,他们可以与 table 中的另一个人“成为好友”。我必须存储谁是谁的朋友的方式是二叉搜索树。对于哈希表,我要做的是节点的第一部分是人名,然后 next 是指向那个人朋友的 bst 的指针,最后是指向下一个节点的指针,如果有的话是碰撞。这是一个视觉示例...

我已经能够将人插入我的表中,但我不知道如何访问 BST 并为那个人添加朋友。这是我的代码...

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

// Structures
struct linkedList{
    char *name;
    struct linkedList *next;
    struct linkedList *tree;
};

typedef struct linkedList list;

struct hashTable{
    int size;
    list **table;
};

typedef struct hashTable hash;

struct bst{
    char *val;
    struct bst *l;
    struct bst *r;
};

int main(){
char input[50];
char *ch, cmd_str[50], name[30];

// Make hash table for names
hash *profiles;
profiles = createHashTable(1001);

while(1){
    // Get keyboard input
    fgets(input, 50, stdin);
    input[strlen(input)-1] = '\0';

    // parse the input
    ch = strtok(input, " ");
    strcpy(cmd_str,ch);



    if(strcmp("CREATE", cmd_str) == 0){
        ch = strtok(NULL, " \n");
        insertPerson(profiles, ch);
    }
    else if(strcmp("FRIEND", cmd_str) == 0){
        ch = strtok(NULL, " \n");
        strcpy(name, ch);
        ch = strtok(NULL, " \n");
        friendPerson(profiles, name, ch);
    }
    else if(strcmp("UNFRIEND", cmd_str) == 0){
        ch = strtok(NULL, " \n");

    }
    else if(strcmp("LIST", cmd_str) == 0){
        ch = strtok(NULL, " \n");
        printFriends(profiles, ch);
    }
    else if(strcmp("QUERY", cmd_str) == 0){

    }
    else if(strcmp("BIGGEST-FRIEND-CIRCLE", cmd_str) == 0){

    }
    else if(strcmp("INFLUENTIAL-FRIEND", cmd_str) == 0){

    }
    else if(strcmp("EXIT", cmd_str) == 0){
        printf("\nExiting...\n");
        return 0;
    }
    else{
        printf("\nBad Command.\n");
    }
}
}

// Creates Hash Table
hash *createHashTable(int size){
int i;
hash *new_table;

if((new_table = malloc(sizeof(hash))) == NULL)
    return NULL;

if((new_table->table = malloc(sizeof(list *) * size)) == NULL)
    return NULL;

for(i=0; i < size; i++)
    new_table->table[i] = NULL;

new_table->size = size;

return new_table;
}

// hashing function
int keyHash(char *name){
    int c;
    unsigned long key;

    while(c = *name++)
        key = ((key<<5) + key) + c;

    return key%1000;
 }

// insert a person into the hash table
void insertPerson(hash *profiles, char *name){
    struct linkedList *item = (struct linkedList*)malloc(sizeof(struct linkedList));
    int hash_val = keyHash(name);

    item->name = name;
    item->next = NULL;
    item->tree = new_tree;

    // Collision case
    if(profiles->table[hash_val] != NULL){
        while(profiles->table[hash_val]->next != NULL){
            profiles->table[hash_val] = profiles->table[hash_val]->next;
        }
        profiles->table[hash_val]->next = item;
    }
    // Empty cell
    else{
        profiles->table[hash_val] = item;
    }

}

// friend two people inside the hash table
void friendPerson(hash *profiles, char *name, char *_friend){
    int hash1 = keyHash(name);
    int hash2 = keyHash(_friend);

    // check if the names are already in system
    if(!profiles->table[hash1]){
        printf("%s is not yet in the system", name);
        return;
    }
    if(!profiles->table[hash2]){
        printf("%s is not yet in the system", _friend);
        return;
    }

    // add first friend
    if(strcmp(profiles->table[hash1]->name, name) == 0){
        insertBST(profiles->table[hash1]->tree, _friend);
    }
    else{
        while(profiles->table[hash1]->next != NULL){
            if(strcmp(profiles->table[hash1]->name, name) == 0)){
                break;
            }
            profiles->table[hash1] = profiles->table[hash1]->next;
        }
        insertBST(profiles->table[hash1]->tree, _friend);
    }

    // add second friend
    if(strcmp(profiles->table[hash2]->name, _friend) == 0){
        insertBST(profiles->table[hash2]->tree, name);
    }
    else{
        while(profiles->table[hash2]->next != NULL){
            if(strcmp(profiles->table[hash2]->name, name) == 0)){
                break;
            }
            profiles->table[hash2] = profiles->table[hash1]->next;
        }
        insertBST(profiles->table[hash2]->tree, name);
    }
}

// creates a new bst node
struct bst *newBSTNode(char *name){
    struct bst *temp = (struct bst* )malloc(sizeof(struct bst));
    temp->val = strdup(name);
    strcpy(temp->val, name);
    temp->l = temp->r = NULL;
    return temp;
}

// Inserts the a friend into a BST
struct bst *insertBST(struct bst *node, char *name){
    if(!node)
        return newBSTNode(name);
    else{
        if(strcmp(name, node->val) < 0){
            node->l = insertBST(node->l, name);
        }
        else if(strcmp(name, node->val) > 0){
            node->r = insertBST(node->r, name);
        }
    }

    return node;
}

// Inorder print of names
void inorder(struct bst *root){
    if(!root){
         inorder(root->l);
         printf("%s ", root->val);
         inorder(root->r);
    }
}

// Sends to function to print names
void printFriends(hash *profiles, char *name){
    int hash_val = keyHash(name);
    inorder(profiles->table[hash_val]->tree);
}

我如何才能访问该人的 BST? struct bst *tree = profiles-&gt;table[hash1]-&gt;tree; 是我之前的尝试,但它更像是在黑暗中拍摄。提前致谢!

更新:好的,所以我已经能够添加朋友(我想),现在我正在尝试使用void printFriends() 打印它们。但是,当我运行该功能时,什么也没有打印出来。有谁知道我在哪里搞砸了?我已经更新了上面的代码。

【问题讨论】:

  • 也许将结构体linkedListtree 的类型更改为bst 会有帮助吗?
  • friend 不是 C 中的关键字。除非您有一些不明显的编码标准,否则您不必使用 _friend
  • 你们说的都对!为了安全起见,我只是使用_friend。但是,知道未来是非常好的!

标签: c algorithm hashtable binary-search-tree


【解决方案1】:

您的linkedList 存储nametree 指针。但是tree 的类型是linkedList。将其更改为 struct bst *。您必须重新排序声明,或插入前向声明。

执行搜索。您检查哈希桶是否为空,但您不搜索匹配的名称。

一旦您在存储桶中找到匹配的名称,同一节点就会包含上述tree 指针。将朋友插入树中。根据您的逻辑,您可能希望也可能不希望在其他人的树中插入反向引用。 (如果 Alice 是 Bob 的朋友,那会自动让 Bob 和 Alice 成为朋友吗?还是等待确认?)

【讨论】:

  • 如此简单的改变!基本上我可以使用profiles-&gt;table[hash1]-&gt;tree 来获取根目录。谢谢你指出来。是的,我将毫无疑问地必须对对方的树进行反向引用。当您与某人成为朋友/取消朋友时,它会自动更改。再次感谢您的回答!
  • 我在将朋友添加到树时遇到了另一个问题。你介意再看一遍吗?我更新了我的代码和问题。再次感谢您的帮助!
  • 您仍然没有搜索冲突。查看您的示例图片 - 如果 Sam 和 Liza 都散列到同一个存储桶,您需要遍历列表以找到正确的字符串。
  • 我认为您在inorder 中的情况是错误的。你正在做由if (!root) 保护的所有事情,基本上是if (root == NULL)。我怀疑你想要if (root)
  • 你说得对,如果发生碰撞,我完全忘记将其从列表中删除。我输入了一个遍历语句,以防万一发生冲突,它会搜索正确的字符串。真正奇怪的部分是printFriends()。我将 if(!root) 更改为 if(root) (出于某种原因,我在此处扔了一个“!”...),但我什至没有得到任何输出。
猜你喜欢
  • 2013-09-26
  • 1970-01-01
  • 2016-03-25
  • 2011-10-14
  • 2011-09-15
  • 2012-06-03
  • 2021-09-14
  • 2013-05-31
相关资源
最近更新 更多