在C中,使用哈希表(Hash Table)或红黑树(Red-Black Tree)都可以很好地实现去重操作。
哈希表是一种基于哈希函数实现的数据结构,可以快速地插入、查找和删除元素。哈希表的时间复杂度为 O(1),但是需要消耗额外的空间来存储哈希表本身。在哈希表中,元素的去重是通过将元素的值作为键值存储在哈希表中实现的。
红黑树是一种自平衡的二叉搜索树,可以保证插入、查找和删除操作的时间复杂度为 O(log n)。红黑树的空间复杂度比哈希表略高,但是可以支持更多的操作,例如按顺序遍历元素。在红黑树中,元素的去重是通过比较元素的大小来实现的。
选择使用哈希表还是红黑树,取决于具体的应用场景和需求。如果需要快速地插入、查找和删除元素,并且可以接受额外的空间消耗,那么可以选择哈希表。如果需要支持更多的操作,并且可以接受略高的空间消耗,那么可以选择红黑树。
红黑树方案
红黑树是一种自平衡的二叉搜索树,它的插入、删除和查找操作的时间复杂度都是 O(log n)。因此,可以使用红黑树进行去重操作。
以下是使用红黑树进行去重的设计方案:
定义一个红黑树结构体,包含一个指向根节点的指针和一个计数器,用于记录树中元素的个数。
定义一个结构体,用于存储需要去重的元素。该结构体包含一个指向下一个元素的指针和一个用于比较元素大小的函数指针。
实现一个插入函数,用于将元素插入红黑树中。插入时,先使用比较函数判断元素是否已经存在于树中,如果不存在,则将元素插入到树中,并将计数器加一。
实现一个删除函数,用于从红黑树中删除元素。删除时,先使用比较函数查找元素是否存在于树中,如果存在,则将元素从树中删除,并将计数器减一。
实现一个查找函数,用于查找元素是否存在于红黑树中。查找时,使用比较函数在树中查找元素,如果找到了,则返回 true,否则返回 false。
在需要去重的地方,先定义一个红黑树结构体和一个用于比较元素大小的函数指针。然后,将需要去重的元素插入到红黑树中,重复元素会被自动去重。
在程序结束时,记得释放红黑树中的内存。
/*
在C中,使用哈希表(Hash Table)或红黑树(Red-Black Tree)都可以很好地实现去重操作。
哈希表是一种基于哈希函数实现的数据结构,可以快速地插入、查找和删除元素。哈希表的时间复杂度为 O(1),但是需要消耗额外的空间来存储哈希表本身。在哈希表中,元素的去重是通过将元素的值作为键值存储在哈希表中实现的。
红黑树是一种自平衡的二叉搜索树,可以保证插入、查找和删除操作的时间复杂度为 O(log n)。红黑树的空间复杂度比哈希表略高,但是可以支持更多的操作,例如按顺序遍历元素。在红黑树中,元素的去重是通过比较元素的大小来实现的。
选择使用哈希表还是红黑树,取决于具体的应用场景和需求。如果需要快速地插入、查找和删除元素,并且可以接受额外的空间消耗,那么可以选择哈希表。如果需要支持更多的操作,并且可以接受略高的空间消耗,那么可以选择红黑树。
红黑树的空间复杂度比哈希表略高,是因为红黑树需要存储每个节点的指针、颜色和值等信息,而哈希表只需要存储键值对即可。
具体来说,红黑树中每个节点需要存储以下信息:
指向左子节点的指针
指向右子节点的指针
父节点指针
颜色信息(红色或黑色)
值信息
而哈希表中每个键值对只需要存储以下信息:
键信息
值信息
因此,红黑树的空间复杂度比哈希表略高[哈希表空间复杂度O(n)]。但是,红黑树的空间复杂度仍然是 O(n),其中 n 是元素的个数,因此在大多数情况下,红黑树的空间消耗是可以接受的。
#include
#include
#include
typedef struct rb_node {
struct rb_node *left;
struct rb_node *right;
bool is_red;
void *data;
} rb_node;
typedef struct rb_tree {
rb_node *root;
int count;
int (*compare)(const void *, const void *);
} rb_tree;
typedef struct element {
struct element *next;
int value;
} element;
int compare_element(const void *a, const void *b) {
const element *ea = (const element *)a;
const element *eb = (const element *)b;
return ea->value - eb->value;
}
rb_node *rb_create_node(void *data) {
rb_node *node = (rb_node *)malloc(sizeof(rb_node));
node->left = NULL;
node->right = NULL;
node->is_red = true;
node->data = data;
return node;
}
void rb_destroy_node(rb_node *node) {
free(node);
}
void rb_destroy(rb_tree *tree) {
if (tree == NULL) {
return;
}
rb_node *node = tree->root;
while (node != NULL) {
if (node->left != NULL) {
rb_node *left = node->left;
node->left = left->right;
left->right = node;
node = left;
} else if (node->right != NULL) {
rb_node *right = node->right;
rb_destroy_node(node);
node = right;
} else {
rb_destroy_node(node);
node = NULL;
}
}
free(tree);
}
rb_tree *rb_create(int (*compare)(const void *, const void *)) {
rb_tree *tree = (rb_tree *)malloc(sizeof(rb_tree));
tree->root = NULL;
tree->count = 0;
tree->compare = compare;
return tree;
}
void rb_rotate_left(rb_node **node) {
rb_node *right = (*node)->right;
(*node)->right = right->left;
right->left = *node;
right->is_red = (*node)->is_red;
(*node)->is_red = true;
*node = right;
}
void rb_rotate_right(rb_node **node) {
rb_node *left = (*node)->left;
(*node)->left = left->right;
left->right = *node;
left->is_red = (*node)->is_red;
(*node)->is_red = true;
*node = left;
}
void rb_flip_colors(rb_node *node) {
node->is_red = true;
node->left->is_red = false;
node->right->is_red = false;
}
void rb_insert_node(rb_node **node, void *data, int (*compare)(const void *, const void *)) {
if (*node == NULL) {
*node = rb_create_node(data);
return;
}
if (compare(data, (*node)->data) < 0) {
rb_insert_node(&(*node)->left, data, compare);
} else if (compare(data, (*node)->data) > 0) {
rb_insert_node(&(*node)->right, data, compare);
} else {
return;
}
if ((*node)->right != NULL && (*node)->right->is_red && (*node)->left != NULL && !(*node)->left->is_red) {
rb_rotate_left(node);
}
if ((*node)->left != NULL && (*node)->left->is_red && (*node)->left->left != NULL && (*node)->left->left->is_red) {
rb_rotate_right(node);
}
if ((*node)->left != NULL && (*node)->left->is_red && (*node)->right != NULL && (*node)->right->is_red) {
rb_flip_colors(*node);
}
}
void rb_insert(rb_tree *tree, void *data) {
rb_insert_node(&tree->root, data, tree->compare);
tree->root->is_red = false;
tree->count++;
}
rb_node *rb_find_node(rb_node *node, void *data, int (*compare)(const void *, const void *)) {
if (node == NULL) {
return NULL;
}
if (compare(data, node->data) < 0) {
return rb_find_node(node->left, data, compare);
} else if (compare(data, node->data) > 0) {
return rb_find_node(node->right, data, compare);
} else {
return node;
}
}
bool rb_find(rb_tree *tree, void *data) {
return rb_find_node(tree->root, data, tree->compare) != NULL;
}
void rb_delete_node(rb_node **node, void *data, int (*compare)(const void *, const void *)) {
if (*node == NULL) {
return;
}
if (compare(data, (*node)->data) < 0) {
if ((*node)->left != NULL && !(*node)->left->is_red && ((*node)->left->left == NULL || !(*node)->left->left->is_red)) {
rb_move_red_left(node);
}
rb_delete_node(&(*node)->left, data, compare);
} else {
if ((*node)->left != NULL && (*node)->left->is_red) {
rb_rotate_right(node);
}
if (compare(data, (*node)->data) == 0 && (*node)->right == NULL) {
rb_destroy_node(*node);
*node = NULL;
return;
}
if ((*node)->right != NULL && !(*node)->right->is_red && ((*node)->right->left == NULL || !(*node)->right->left->is_red)) {
rb_move_red_right(node);
}
if (compare(data, (*node)->data) == 0) {
rb_node *min = rb_min_node((*node)->right);
(*node)->data = min->data;
rb_delete_min_node(&(*node)->right);
} else {
rb_delete_node(&(*node)->right, data, compare);
}
}
rb_fixup(node);
}
void rb_delete(rb_tree *tree, void *data) {
if (rb_find(tree, data)) {
rb_delete_node(&tree->root, data, tree->compare);
tree->count--;
if (tree->root != NULL) {
tree->root->is_red = false;
}
}
}
int main() {
element e1 = { NULL, 1 };
element e2 = { NULL, 2 };
element e3 = { NULL, 3 };
element e4 = { NULL, 2 };
element e5 = { NULL, 4 };
rb_tree *tree = rb_create(compare_element);
rb_insert(tree, &e1);
rb_insert(tree, &e2);
rb_insert(tree, &e3);
rb_insert(tree, &e4);
rb_insert(tree, &e5);
printf("%d\n", tree->count); // output: 4
rb_destroy(tree);
return 0;
}
*/
哈希表去重方案
在 C 语言中,可以使用哈希表(Hash Table)进行去重操作。
哈希表是一种基于哈希函数实现的数据结构,可以快速地插入、查找和删除元素。在哈希表中,元素的去重是通过将元素的值作为键值存储在哈希表中实现的。
以下是使用哈希表进行去重的设计方案:
定义一个哈希表结构体,包含一个指向哈希桶的指针和一个计数器,用于记录哈希表中元素的个数。
定义一个结构体,用于存储需要去重的元素。该结构体包含一个指向下一个元素的指针和一个用于比较元素大小的函数指针。
实现一个哈希函数,将元素的值转换为哈希桶的索引。可以使用简单的取模运算或者更复杂的哈希算法来实现哈希函数。
实现一个插入函数,用于将元素插入哈希表中。插入时,先使用哈希函数计算元素的哈希桶索引,然后在对应的哈希桶中查找元素是否已经存在。如果不存在,则将元素插入到哈希桶中,并将计数器加一。
实现一个删除函数,用于从哈希表中删除元素。删除时,先使用哈希函数计算元素的哈希桶索引,然后在对应的哈希桶中查找元素是否存在。如果存在,则将元素从哈希桶中删除,并将计数器减一。
实现一个查找函数,用于查找元素是否存在于哈希表中。查找时,先使用哈希函数计算元素的哈希桶索引,然后在对应的哈希桶中查找元素,如果找到了,则返回 true,否则返回 false。
在需要去重的地方,先定义一个哈希表结构体和一个用于比较元素大小的函数指针。然后,将需要去重的元素插入到哈希表中,重复元素会被自动去重。
在程序结束时,记得释放哈希表中的内存
#include
#include
#include
#define HASH_SIZE 100
typedef struct hash_node {
struct hash_node *next;
void *data;
} hash_node;
typedef struct hash_table {
hash_node *buckets[HASH_SIZE];
int count;
int (*hash)(const void *);
int (*compare)(const void *, const void *);
} hash_table;
typedef struct element {
struct element *next;
int value;
} element;
int hash_element(const void *data) {
const element *e = (const element *)data;
return e->value % HASH_SIZE;
}
int compare_element(const void *a, const void *b) {
const element *ea = (const element *)a;
const element *eb = (const element *)b;
return ea->value - eb->value;
}
hash_node *hash_create_node(void *data) {
hash_node *node = (hash_node *)malloc(sizeof(hash_node));
node->next = NULL;
node->data = data;
return node;
}
void hash_destroy_node(hash_node *node) {
free(node);
}
void hash_destroy(hash_table *table) {
if (table == NULL) {
return;
}
for (int i = 0; i < HASH_SIZE; i++) {
hash_node *node = table->buckets[i];
while (node != NULL) {
hash_node *next = node->next;
hash_destroy_node(node);
node = next;
}
}
free(table);
}
hash_table *hash_create(int (*hash)(const void *), int (*compare)(const void *, const void *)) {
hash_table *table = (hash_table *)malloc(sizeof(hash_table));
for (int i = 0; i < HASH_SIZE; i++) {
table->buckets[i] = NULL;
}
table->count = 0;
table->hash = hash;
table->compare = compare;
return table;
}
void hash_insert(hash_table *table, void *data) {
int index = table->hash(data);
hash_node *node = table->buckets[index];
while (node != NULL) {
if (table->compare(data, node->data) == 0) {
return;
}
node = node->next;
}
node = hash_create_node(data);
node->next = table->buckets[index];
table->buckets[index] = node;
table->count++;
}
void hash_remove(hash_table *table, void *data) {
int index = table->hash(data);
hash_node *node = table->buckets[index];
hash_node *prev = NULL;
while (node != NULL) {
if (table->compare(data, node->data) == 0) {
if (prev == NULL) {
table->buckets[index] = node->next;
} else {
prev->next = node->next;
}
hash_destroy_node(node);
table->count--;
return;
}
prev = node;
node = node->next;
}
}
bool hash_contains(hash_table *table, void *data) {
int index = table->hash(data);
hash_node *node = table->buckets[index];
while (node != NULL) {
if (table->compare(data, node->data) == 0) {
return true;
}
node = node->next;
}
return false;
}
int main() {
hash_table *table = hash_create(hash_element, compare_element);
element e1 = {NULL, 1};
element e2 = {NULL, 2};
element e3 = {NULL, 3};
element e4 = {NULL, 2};
hash_insert(table, &e1);
hash_insert(table, &e2);
hash_insert(table, &e3);
hash_insert(table, &e4);
printf("count: %d\n", table->count); // count: 3
hash_remove(table, &e2);
printf("count: %d\n", table->count); // count: 2
printf("contains e2: %d\n", hash_contains(table, &e2)); // contains e2: 0
hash_destroy(table);
return 0;
}