使用c语言,实现一个HashMap的数据结构,"该HashMap与JAVA语言中的HashMap有相似的功能,利用链表和红黑树等数据结构,实现O(1)时间的复杂度进行插入,删除等操作,具体包括put、get、resize、remove、treeifyBin方法。
当<k,v>键值对达到7以上,要调用treeifyBin方法实现链表转化为红黑树存储"
// 定义哈希表中的节点结构
typedef struct Node {
char *key;
int value;
struct Node *next;
} Node;
typedef enum {
Link,
RED_BLACK_TREE
} BucketType;
// 定义哈希表结构
typedef struct {
int capacity;
int size;
Node **buckets;
BucketType *bucket_types; // 新增的标记桶数据结构类型的成员
} HashMap;
// 定义红黑树节点结构
typedef struct RBNode {
char *key;
int value;
struct RBNode *left;
struct RBNode *right;
struct RBNode *parent; // 添加指向父节点的指针
int color; // 0 for Black, 1 for Red
} RBNode;
//创建哈希表
HashMap *createHashMap() {
HashMap *map = (HashMap *) malloc(sizeof(HashMap));
map->capacity = INITIAL_CAPACITY;
map->size = 0;
map->buckets = (Node **) calloc(map->capacity, sizeof(Node *));
map->bucket_types = (BucketType *) calloc(map->capacity, sizeof(BucketType)); // 初始化 bucket_types 数组
for (int i = 0; i < map->capacity; ++i) {
map->buckets[i] = NULL;
map->bucket_types[i] = Link; // 初始情况下,所有桶都被标记为列表类型
}
return map;
}
// 重载的方法 可以传递容量大小 用于初始化
HashMap *createHashMapS(int capacity) {
HashMap *map = (HashMap *) malloc(sizeof(HashMap));
map->capacity = capacity;
map->size = 0;
map->buckets = (Node **) calloc(map->capacity, sizeof(Node *));
map->bucket_types = (BucketType *) calloc(map->capacity, sizeof(BucketType)); // 初始化 bucket_types 数组
for (int i = 0; i < map->capacity; ++i) {
map->buckets[i] = NULL;
map->bucket_types[i] = Link; // 初始情况下,所有桶都被标记为列表类型
}
return map;
}
// 散列函数
int hash(char *key, int capacity) {
int hash = 0;
while (*key) {
hash = (hash * 31 + *key) % capacity;
key++;
}
return hash;
测试红黑树 一直添加到桶序号为10的下面
// return 10;
}
// 计算红黑树节点数量
int countNodes(RBNode *root) {
if (root == NULL) {
return 0;
}
// 递归计算左子树和右子树的节点数量,并加上根节点
return 1 + countNodes(root->left) + countNodes(root->right);
}
// 计算指定桶的大小
int bucketSize(HashMap *map, int index) {
if (index < 0 || index >= map->capacity) {
return 0;
}
int count = 0;
BucketType bucket_type = map->bucket_types[index];
//如果是红黑树结点
if (bucket_type == RED_BLACK_TREE) {
RBNode *root = (RBNode *) map->buckets[index];
return countNodes(root);
} else {
Node *node = map->buckets[index];
while (node) {
count++;
node = node->next;
}
return count;
}
}
// 从红黑树中获取值
int getValueFromRedBlackTree(RBNode *root, char *key) {
// 遍历红黑树,查找对应的键值对
while (root != NULL) {
int cmp = strcmp(key, root->key);
if (cmp == 0) {
return root->value; // 找到对应的键值对,返回值
} else if (cmp < 0) {
root = root->left; // 当前键值小于根节点的键值,移动到左子树继续查找
} else {
root = root->right; // 当前键值大于根节点的键值,移动到右子树继续查找
}
}
return -1; // 未找到对应键的值
}
// 从哈希表中获取值
int get(HashMap *map, char *key) {
int index = hash(key, map->capacity);
BucketType bucket_type = map->bucket_types[index];
if (bucket_type == RED_BLACK_TREE) {
RBNode *root = map->buckets[index];
//通过对红黑树树的遍历查找对应的key
return getValueFromRedBlackTree(root, key);
} else {
Node *node = map->buckets[index];
while (node) {
if (strcmp(node->key, key) == 0) {
return node->value;
}
node = node->next;
}
return -1; // 未找到对应键的值
}
}
// 释放红黑树内存(辅助函数)
void freeRBTree(RBNode *root) {
if (root == NULL) {
return;
}
freeRBTree(root->left);
freeRBTree(root->right);
free(root->key);
free(root);
}
// 左旋
void rotateLeft(RBNode **root, RBNode *node) {
RBNode *rightChild = node->right;
node->right = rightChild->left;
if (node->right != NULL) {
node->right->parent = node; // 这里需要更新右子节点的父节点指针
}
rightChild->parent = node->parent; // 更新右子节点的父节点指针
if (node->parent == NULL) {
*root = rightChild;
} else if (node == node->parent->left) {
node->parent->left = rightChild;
} else {
node->parent->right = rightChild;
}
rightChild->left = node;
node->parent = rightChild;
}
// 右旋
void rotateRight(RBNode **root, RBNode *node) {
RBNode *leftChild = node->left;
node->left = leftChild->right;
if (node->left != NULL) {
node->left->parent = node;
}
leftChild->parent = node->parent;
if (node->parent == NULL) {
*root = leftChild;
} else if (node == node->parent->left) {
node->parent->left = leftChild;
} else {
node->parent->right = leftChild;
}
leftChild->right = node;
node->parent = leftChild;
}
// 红黑树插入修正
void insertFixup(RBNode **root, RBNode *node) {
while (node != NULL && node != *root && node->parent->parent != NULL && node->parent->color == 1) {
// 如果当前节点的父节点是祖父节点的左孩子
//相当于需要右旋了
if (node->parent == node->parent->parent->left) {
RBNode *uncle = node->parent->parent->right; // 获取当前节点的叔节点
// 情况1:叔节点也为红色
if (uncle != NULL && uncle->color == 1) {
node->parent->color = 0; // 将父节点设为黑色
uncle->color = 0; // 将叔节点设为黑色
node->parent->parent->color = 1; // 将祖父节点设为红色
node = node->parent->parent; // 将当前节点指向祖父节点,继续向上修正
} else {
// 情况2:当前节点为父节点的右孩子
if (node == node->parent->right) {
node = node->parent; // 将当前节点指向父节点
rotateLeft(root, node); // 左旋
}
node->parent->color = 0; // 将父节点设为黑色
if (node->parent->parent != NULL) {
node->parent->parent->color = 1; // 将祖父节点设为红色
rotateRight(root, node->parent->parent); // 右旋
}
}
} else {
// 如果当前节点的父节点是祖父节点的右孩子(与上述情况对称)
RBNode *uncle = node->parent->parent->left;
// 情况1:叔节点也为红色
if (uncle != NULL && uncle->color == 1) {
node->parent->color = 0; // 将父节点设为黑色
uncle->color = 0; // 将叔节点设为黑色
node->parent->parent->color = 1; // 将祖父节点设为红色
node = node->parent->parent; // 将当前节点指向祖父节点,继续向上修正
} else {
// 情况2:当前节点为父节点的左孩子(与上述情况对称)
if (node == node->parent->left) {
node = node->parent; // 将当前节点指向父节点
rotateRight(root, node); // 右旋
}
node->parent->color = 0; // 将父节点设为黑色
if (node->parent->parent != NULL) {
node->parent->parent->color = 1; // 将祖父节点设为红色
rotateLeft(root, node->parent->parent); // 左旋
}
}
}
}
(*root)->color = 0; // 根节点始终为黑色
}
// 将链表转换为红黑树
void treeifyBin(HashMap *map, int index) {
源码:
百度链接
https://pan.baidu.com/s/1ZqQ0XxOQ_mFaXWempYpB3w?pwd=rwfl
提取码:rwfl