-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdictionary.c
More file actions
127 lines (106 loc) · 3.48 KB
/
dictionary.c
File metadata and controls
127 lines (106 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "dictionary.h"
/** ----------------------------------------------------------------------------
* Dictionary functions */
// Create dictionary, with a in built function to compare values
dict_t
*makedict(cmp_t _cmp) {
dict_t *dict = malloc(sizeof(dict_t));
assert(dict != NULL);
dict -> root = NULL;
dict -> cmp = _cmp;
return dict;
};
// Insert key-value pair into dictionary
void
insert(dict_t *dict, void *key, void *value) {
_traverse_and_insert(dict -> root, key, value, &(dict -> root),
dict -> cmp);
}
// Return all values with matching key in a linked list
list_node_t
*search(dict_t* dict, void* key, int *cmp_used) {
assert(dict);
*cmp_used = 0;
return _traverse_to_key(dict -> root, key, cmp_used, dict -> cmp);
}
// Free dictionary, takes a function that frees the data structure pointed by
// * void *value */
void
free_dict(dict_t *dict, void (*_free)(void *value)) {
_traverse_and_free(dict -> root, _free);
free(dict);
}
/** ----------------------------------------------------------------------------
* Helper function implementations */
/* Make new linked list node */
list_node_t
*_new_list_node(void *value) {
list_node_t *list_node = malloc(sizeof(list_node_t));
assert(list_node != NULL);
list_node -> value = value;
list_node -> next = NULL;
return list_node;
}
/* Recursive implementation to insert value into tree */
void
_traverse_and_insert(tree_node_t *node, void* key, void *value,
tree_node_t **prev_pointer, cmp_t cmp) {
int dif;
/* Create new tree node if needed, and add node to parent */
if (node == NULL) {
node = malloc(sizeof(tree_node_t));
assert(node != NULL);
node -> left = node -> right = NULL;
node -> key = key;
list_node_t *list_head = _new_list_node(value);
node -> list_head = list_head;
*prev_pointer = node;
}
/* Add value to linked list if key matches */
else if ((dif = cmp(key, node -> key)) == 0) {
list_node_t *cur = node -> list_head;
list_node_t *new_node = _new_list_node(value);
while (cur -> next != NULL) cur = cur -> next;
cur -> next = new_node;
}
/* Else traverse to child */
else if (dif < 0){
_traverse_and_insert(node -> left, key, value, &(node -> left), cmp);
}
else {
_traverse_and_insert(node -> right, key, value, &(node -> right), cmp);
}
}
/* Recursive implementation to search for a key in the tree */
list_node_t
*_traverse_to_key(tree_node_t *node, void *key, int *cmp_used, cmp_t cmp) {
if (node == NULL) return NULL;
int dif;
++*cmp_used;
if ( (dif = cmp(key, node -> key)) < 0 ) {
return _traverse_to_key(node -> left, key, cmp_used, cmp);
}
else if ( dif > 0 ) {
return _traverse_to_key(node -> right, key, cmp_used, cmp);
}
else {
return node -> list_head;
}
}
/* Perform action for each node in the tree with post-order traversal */
void
_traverse_and_free(tree_node_t *node, void (*_free)(void *value)) {
if (node == NULL) return;
_traverse_and_free(node -> left, _free);
_traverse_and_free(node -> right, _free);
list_node_t *cur_elem = node -> list_head;
list_node_t *next_elem;
while (cur_elem != NULL) {
_free(cur_elem -> value);
next_elem = cur_elem -> next;
free(cur_elem);
cur_elem = next_elem;
}
free(node -> key);
free(node);
}