SlideShare a Scribd company logo
1
Data Structures and Algorithms
!
The material for this lecture is drawn, in part, from!
The Practice of Programming (Kernighan & Pike) Chapter 2!
Jennifer Rexford
!
2
Motivating Quotations!
“Every program depends on algorithms and data
structures, but few programs depend on the
invention of brand new ones.”!
-- Kernighan & Pike!
“I will, in fact, claim that the difference between a
bad programmer and a good one is whether he
considers his code or his data structures more
important. Bad programmers worry about the
code. Good programmers worry about data
structures and their relationships.”!
-- Linus Torvalds!
3
Goals of this Lecture!
• Help you learn (or refresh your memory) about:!
• Common data structures and algorithms!
• Why? Shallow motivation:!
• Provide examples of pointer-related C code!
• Why? Deeper motivation:!
• Common data structures and algorithms serve as “high
level building blocks”!
• A power programmer:!
• Rarely creates programs from scratch!
• Often creates programs using building blocks!
4
A Common Task!
• Maintain a table of key/value pairs!
• Each key is a string; each value is an int
• Unknown number of key-value pairs!
• Examples!
• (student name, grade)!
• (“john smith”, 84), (“jane doe”, 93), (“bill clinton”, 81)!
• (baseball player, number)!
• (“Ruth”, 3), (“Gehrig”, 4), (“Mantle”, 7)!
• (variable name, value)!
• (“maxLength”, 2000), (“i”, 7), (“j”, -10)!
• For simplicity, allow duplicate keys (client responsibility)!
• In Assignment #3, must check for duplicate keys!!
5
Data Structures and Algorithms!
• Data structures!
• Linked list of key/value pairs!
• Hash table of key/value pairs!
• Algorithms!
• Create: Create the data structure!
• Add: Add a key/value pair!
• Search: Search for a key/value pair, by key!
• Free: Free the data structure!
6
Data Structure #1: Linked List!
• Data structure: Nodes; each contains key/value
pair and pointer to next node!
• Algorithms:!
• Create: Allocate Table structure to point to first node!
• Add: Insert new node at front of list!
• Search: Linear search through the list!
• Free: Free nodes while traversing; free Table structure!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
7
Linked List: Data Structure!
struct Node {
const char *key;
int value;
struct Node *next;
};
struct Table {
struct Node *first;
};
4
"Gehrig"
3
"Ruth"
NULL
struct!
Table!
struct!
Node!
struct!
Node!
8
Linked List: Create (1)!
t!
struct Table *Table_create(void) {
struct Table *t;
t = (struct Table*)
malloc(sizeof(struct Table));
t->first = NULL;
return t;
}
struct Table *t;
…
t = Table_create();
…
9
Linked List: Create (2)!
struct Table *Table_create(void) {
struct Table *t;
t = (struct Table*)
malloc(sizeof(struct Table));
t->first = NULL;
return t;
}
struct Table *t;
…
t = Table_create();
…
t!
NULL
10
Linked List: Add (1)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
p->value = value;
p->next = t->first;
t->first = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
These are
pointers to!
strings!
4
"Gehrig"
3
"Ruth"
NULL
t!
11
Linked List: Add (2)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
p->value = value;
p->next = t->first;
t->first = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
4
"Gehrig"
3
"Ruth"
NULL
t!
p!
12
Linked List: Add (3)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
p->value = value;
p->next = t->first;
t->first = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p!
13
Linked List: Add (4)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
p->value = value;
p->next = t->first;
t->first = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p!
14
Linked List: Add (5)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
p->value = value;
p->next = t->first;
t->first = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p!
15
Linked List: Search (1)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
16
Linked List: Search (2)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
p!
17
Linked List: Search (3)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
p!
18
Linked List: Search (4)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
p!
19
Linked List: Search (5)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
p!
20
Linked List: Search (6)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
for (p = t->first; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
t!
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
p! 4
1
21
Linked List: Free (1)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
22
Linked List: Free (2)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p!
23
Linked List: Free (3)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
24
Linked List: Free (4)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
25
Linked List: Free (5)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
26
Linked List: Free (6)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
27
Linked List: Free (7)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
28
Linked List: Free (8)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
29
Linked List: Free (9)!
struct Table *t;
…
Table_free(t);
…
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
for (p = t->first; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t)
}
4
"Gehrig"
3
"Ruth"
NULL
7
"Mantle"
t!
p! nextp!
30
Linked List Performance!
• Create: !fast!
• Add:! !fast!
• Search: !slow!
• Free: !slow!
Would it be better to
keep the nodes
sorted by key?!
What are the
asymptotic run times
(big-oh notation)?!
31
Data Structure #2: Hash Table!
• Fixed-size array where each element points to a linked list!
• Function maps each key to an array index !
• For example, for an integer key h
• Hash function: i = h % ARRAYSIZE (mod function)!
• Go to array element i, i.e., the linked list hashtab[i]
• Search for element, add element, remove element, etc.!
0
ARRAYSIZE-1
struct Node *array[ARRAYSIZE];
32
Hash Table Example!
• Integer keys, array of size 5 with hash function “h
mod 5” !
• “1776 % 5” is 1!
• “1861 % 5” is 1!
• “1939 % 5” is 4!
1776
Revolution
1861
Civil
1939
WW2
0
1
2
3
4
33
How Large an Array?!
• Large enough that average “bucket” size is 1!
• Short buckets mean fast search!
• Long buckets mean slow search!
• Small enough to be memory efficient!
• Not an excessive number of elements!
• Fortunately, each array element is just storing a pointer!
• This is OK:!
0
ARRAYSIZE-1
34
What Kind of Hash Function?!
• Good at distributing elements across the array!
• Distribute results over the range 0, 1, …, ARRAYSIZE-1!
• Distribute results evenly to avoid very long buckets!
• This is not so good:!
0
ARRAYSIZE-1
What would be the
worst possible hash
function?!
35
Hashing String Keys to Integers!
• Simple schemes donʼt distribute the keys evenly enough!
• Number of characters, mod ARRAYSIZE!
• Sum the ASCII values of all characters, mod ARRAYSIZE!
• …!
• Hereʼs a reasonably good hash function!
• Weighted sum of characters xi in the string!
• (Σ aixi) mod ARRAYSIZE!
• Best if a and ARRAYSIZE are relatively prime!
• E.g., a = 65599, ARRAYSIZE = 1024!
36
Implementing Hash Function!
• Potentially expensive to compute ai for each value of i!
• Computing ai for each value of I!
• Instead, do (((x[0] * 65599 + x[1]) * 65599 + x[2]) * 65599 + x[3]) * …!
unsigned int hash(const char *x) {
int i;
unsigned int h = 0U;
for (i=0; x[i]!='0'; i++)
h = h * 65599 + (unsigned char)x[i];
return h % 1024;
}
Can be more clever than this for powers of two!!
(Described in Appendix)!
37
Hash Table Example!
Example: ARRAYSIZE = 7!
Lookup (and enter, if not present) these strings: the, cat, in, the, hat!
Hash table initially empty.!
First word: the. hash(“the”) = 965156977. 965156977 % 7 = 1.!
Search the linked list table[1] for the string “the”; not found.!
0
1
2
3
4
5
6
38
Hash Table Example (cont.)!
Example: ARRAYSIZE = 7!
Lookup (and enter, if not present) these strings: the, cat, in, the, hat!
Hash table initially empty.!
First word: “the”. hash(“the”) = 965156977. 965156977 % 7 = 1.!
Search the linked list table[1] for the string “the”; not found!
Now: table[1] = makelink(key, value, table[1])!
0
1
2
3
4
5
6
the
39
Hash Table Example (cont.)!
Second word: “cat”. hash(“cat”) = 3895848756. 3895848756 % 7 = 2.!
Search the linked list table[2] for the string “cat”; not found!
Now: table[2] = makelink(key, value, table[2])!
0
1
2
3
4
5
6
the
40
Hash Table Example (cont.)!
Third word: “in”. hash(“in”) = 6888005. 6888005% 7 = 5.!
Search the linked list table[5] for the string “in”; not found!
Now: table[5] = makelink(key, value, table[5])!
0
1
2
3
4
5
6
the
cat
41
Hash Table Example (cont.)!
Fourth word: “the”. hash(“the”) = 965156977. 965156977 % 7 = 1.!
Search the linked list table[1] for the string “the”; found it!!
0
1
2
3
4
5
6
the
cat
in
42
Hash Table Example (cont.)!
Fourth word: “hat”. hash(“hat”) = 865559739. 865559739 % 7 = 2.!
Search the linked list table[2] for the string “hat”; not found.!
Now, insert “hat” into the linked list table[2]. !
At beginning or end? Doesnʼt matter.!
0
1
2
3
4
5
6
the
cat
in
43
Hash Table Example (cont.)!
Inserting at the front is easier, so add “hat” at the front !
0
1
2
3
4
5
6
the
hat
in
cat
44
Hash Table: Data Structure!
enum {BUCKET_COUNT = 1024};
struct Node {
const char *key;
int value;
struct Node *next;
};
struct Table {
struct Node *array[BUCKET_COUNT];
};
NULL
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
struct!
Table!
struct!
Node!
struct!
Node!
45
Hash Table: Create!
struct Table *Table_create(void) {
struct Table *t;
t = (struct Table*)calloc(1, sizeof(struct Table));
return t;
}
struct Table *t;
…
t = Table_create();
…
t!
NULL
NULL
NULL
0
1
1023
…
46
Hash Table: Add (1)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
int h = hash(key);
p->key = key;
p->value = value;
p->next = t->array[h];
t->array[h] = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
t!
NULL
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
These are
pointers to
strings!
Pretend that “Ruth”!
hashed to 23 and!
“Gehrig” to 723!
47
Hash Table: Add (2)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
int h = hash(key);
p->key = key;
p->value = value;
p->next = t->array[h];
t->array[h] = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
t!
NULL
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
p!
48
Hash Table: Add (3)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
int h = hash(key);
p->key = key;
p->value = value;
p->next = t->array[h];
t->array[h] = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
t!
NULL
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
7
"Mantle"
p!
Pretend that “Mantle”!
hashed to 806, and so!
h = 806!
49
Hash Table: Add (4)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
int h = hash(key);
p->key = key;
p->value = value;
p->next = t->array[h];
t->array[h] = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
t!
NULL
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
7
"Mantle"
NULL
p!
h = 806!
50
Hash Table: Add (5)!
void Table_add(struct Table *t,
const char *key, int value) {
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
int h = hash(key);
p->key = key;
p->value = value;
p->next = t->array[h];
t->array[h] = p;
}
struct Table *t;
…
Table_add(t, "Ruth", 3);
Table_add(t, "Gehrig", 4);
Table_add(t, "Mantle", 7);
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
NULL
NULL
0
1
806
23
723
…
…
…
NULL
1023
…
7
"Mantle"
NULL
p!
h = 806!
51
Hash Table: Search (1)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key);
for (p = t->array[h]; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
52
Hash Table: Search (2)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key);
for (p = t->array[h]; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
Pretend that “Gehrig”!
hashed to 723, and so!
h = 723!
53
Hash Table: Search (3)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key);
for (p = t->array[h]; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
h = 723!
p!
54
Hash Table: Search (4)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key);
for (p = t->array[h]; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
h = 723!
p!
55
Hash Table: Search (5)!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key);
for (p = t->array[h]; p != NULL; p = p->next)
if (strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
struct Table *t;
int value;
int found;
…
found =
Table_search(t, "Gehrig", &value);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
h = 723!
p! 4
1
56
Hash Table: Free (1)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
57
Hash Table: Free (2)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 0!
58
Hash Table: Free (3)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 0!
p!
59
Hash Table: Free (4)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 1, …, 23!
p!
60
Hash Table: Free (5)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 23!
p!
61
Hash Table: Free (6)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 23!
p!
nextp!
62
Hash Table: Free (7)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 23!
p! nextp!
63
Hash Table: Free (8)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 24, …, 723!
b = 724, …, 806!
b = 807, …, 1024!
64
Hash Table: Free (9)!
void Table_free(struct Table *t) {
struct Node *p;
struct Node *nextp;
int b;
for (b = 0; b < BUCKET_COUNT; b++)
for (p = t->array[b]; p != NULL; p = nextp) {
nextp = p->next;
free(p);
}
free(t);
}
struct Table *t;
…
Table_free(t);
…
…
t!
4
"Gehrig"
NULL
3
"Ruth"
NULL
7
"Mantle"
NULL
…
NULL
NULL
0
1
806
23
723
…
NULL
1023
…
…
b = 1024!
65
Hash Table Performance!
• Create: !fast!
• Add: !fast!
• Search: !fast!
• Free: !slow!
What are the
asymptotic run times
(big-oh notation)?!
Is hash table
search always
fast?!
66
Key Ownership!
• Note: Table_add() functions contain this code:!
• Caller passes key, which is a pointer to memory where a string
resides!
• Table_add() function stores within the table the address where the
string resides!
void Table_add(struct Table *t, const char *key, int value) {
…
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = key;
…
}
67
Key Ownership (cont.)!
• Problem: Consider this calling code:!
struct Table t;
char k[100] = "Ruth";
…
Table_add(t, k, 3);
strcpy(k, "Gehrig");
…
• Via Table_add(), table contains
memory address k!
• Client changes string at
memory address k!
• Thus client changes key within table!
What happens if the
client searches t for
“Ruth”?!
What happens if the
client searches t for
“Gehrig”?!
68
Key Ownership (cont.)!
• Solution: Table_add() saves copy of given key!
• If client changes string at memory address k, data structure is not
affected!
• Then the data structure “owns” the copy, that is:!
• The data structure is responsible for freeing the memory in which
the copy resides!
• The Table_free() function must free the copy!
void Table_add(struct Table *t, const char *key, int value) {
…
struct Node *p = (struct Node*)malloc(sizeof(struct Node));
p->key = (const char*)malloc(strlen(key) + 1);
strcpy(p->key, key);
…
} Why add 1?!
69
Summary!
• Common data structures & associated algorithms!
• Linked list!
• Fast insert, slow search!
• Hash table!
• Fast insert, (potentially) fast search!
• Invaluable for storing key/value pairs!
• Very common!
• Related issues!
• Hashing algorithms!
• Memory ownership!
70
Appendix!
• “Stupid programmer tricks” related to hash tables…!
71
Revisiting Hash Functions!
• Potentially expensive to compute “mod c”!
• Involves division by c and keeping the remainder!
• Easier when c is a power of 2 (e.g., 16 = 24)!
• An alternative (by example)!
• 53 = 32 + 16 + 4 + 1!
• 53 % 16 is 5, the last four bits of the number!
• Would like an easy way to isolate the last four bits… !
0 0 1 1 0 1 0 1
1
2
4
8
16
32
0 0 0 0 0 1 0 1
1
2
4
8
16
32
72
Recall: Bitwise Operators in C!
• Bitwise AND (&)!
• Mod on the cheap!!
• E.g., h = 53 & 15;!
• Bitwise OR (|)!
&
0
1
0 1
0 0
0 1
|
0
1
0 1
0 1
1 1
0 0 1 1 0 1 0 1
0 0 0 0 1 1 1 1
53
& 15
0 0 0 0 0 1 0 1
5
• Oneʼs complement (~)!
• Turns 0 to 1, and 1 to 0!
• E.g., set last three bits to 0!
• x = x & ~7;!
73
A Faster Hash Function!
unsigned int hash(const char *x) {
int i;
unsigned int h = 0U;
for (i=0; x[i]!='0'; i++)
h = h * 65599 + (unsigned char)x[i];
return h % 1024;
}
unsigned int hash(const char *x) {
int i;
unsigned int h = 0U;
for (i=0; x[i]!='0'; i++)
h = h * 65599 + (unsigned char)x[i];
return h & 1023;
}
Faster!
Previous!
version!
What happens if
you mistakenly
write “h & 1024”?!
74
Speeding Up Key Comparisons!
• Speeding up key comparisons!
• For any non-trivial value comparison function!
• Trick: store full hash result in structure!
int Table_search(struct Table *t,
const char *key, int *value) {
struct Node *p;
int h = hash(key); /* No % in hash function */
for (p = t->array[h%1024]; p != NULL; p = p->next)
if ((p->hash == h) && strcmp(p->key, key) == 0) {
*value = p->value;
return 1;
}
return 0;
}
Why is this so
much faster?!

More Related Content

Similar to 08DsAlg.pdf

Linked List.pptx
Linked List.pptxLinked List.pptx
Linked List.pptx
PoonamPatil120
 
Linked list1
Linked list1Linked list1
Linked list1
meghasaddi
 
Linked list
Linked listLinked list
Linked list
A. S. M. Shafi
 
DS_LinkedList.pptx
DS_LinkedList.pptxDS_LinkedList.pptx
DS_LinkedList.pptx
msohail37
 
Chapter14
Chapter14Chapter14
Chapter14
FALLEE31188
 
Unit 5 linked list
Unit   5 linked listUnit   5 linked list
Unit 5 linked list
Dabbal Singh Mahara
 
Data structures
Data structuresData structures
Data structures
Jauhar Amir
 
#include sstream #include linkylist.h #include iostream.pdf
#include sstream #include linkylist.h #include iostream.pdf#include sstream #include linkylist.h #include iostream.pdf
#include sstream #include linkylist.h #include iostream.pdf
aravlitraders2012
 
DS Unit 2.ppt
DS Unit 2.pptDS Unit 2.ppt
DS Unit 2.ppt
JITTAYASHWANTHREDDY
 
This assignment and the next (#5) involve design and development of a.pdf
This assignment and the next (#5) involve design and development of a.pdfThis assignment and the next (#5) involve design and development of a.pdf
This assignment and the next (#5) involve design and development of a.pdf
EricvtJFraserr
 
Adt of lists
Adt of listsAdt of lists
Adt of lists
Nivegeetha
 
Linked list
Linked list Linked list
Linked list
Arbind Mandal
 
IN C LANGUAGE- I've been trying to finish this program for the last fe.docx
IN C LANGUAGE- I've been trying to finish this program for the last fe.docxIN C LANGUAGE- I've been trying to finish this program for the last fe.docx
IN C LANGUAGE- I've been trying to finish this program for the last fe.docx
GordonpACKellyb
 
Data structure
Data  structureData  structure
Data structure
Arvind Kumar
 
Sorting & Linked Lists
Sorting & Linked ListsSorting & Linked Lists
Sorting & Linked Lists
J.T.A.JONES
 
Linked list
Linked listLinked list
Linked list
KalaivaniKS1
 
Unit ii(dsc++)
Unit ii(dsc++)Unit ii(dsc++)
Unit ii(dsc++)
Durga Devi
 
Chapter 5 ds
Chapter 5 dsChapter 5 ds
Chapter 5 ds
Hanif Durad
 
Linked List.ppt Linked List Datastructure concepts
Linked List.ppt Linked List Datastructure conceptsLinked List.ppt Linked List Datastructure concepts
Linked List.ppt Linked List Datastructure concepts
SakkaravarthiShanmug
 
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjhlinked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
vasavim9
 

Similar to 08DsAlg.pdf (20)

Linked List.pptx
Linked List.pptxLinked List.pptx
Linked List.pptx
 
Linked list1
Linked list1Linked list1
Linked list1
 
Linked list
Linked listLinked list
Linked list
 
DS_LinkedList.pptx
DS_LinkedList.pptxDS_LinkedList.pptx
DS_LinkedList.pptx
 
Chapter14
Chapter14Chapter14
Chapter14
 
Unit 5 linked list
Unit   5 linked listUnit   5 linked list
Unit 5 linked list
 
Data structures
Data structuresData structures
Data structures
 
#include sstream #include linkylist.h #include iostream.pdf
#include sstream #include linkylist.h #include iostream.pdf#include sstream #include linkylist.h #include iostream.pdf
#include sstream #include linkylist.h #include iostream.pdf
 
DS Unit 2.ppt
DS Unit 2.pptDS Unit 2.ppt
DS Unit 2.ppt
 
This assignment and the next (#5) involve design and development of a.pdf
This assignment and the next (#5) involve design and development of a.pdfThis assignment and the next (#5) involve design and development of a.pdf
This assignment and the next (#5) involve design and development of a.pdf
 
Adt of lists
Adt of listsAdt of lists
Adt of lists
 
Linked list
Linked list Linked list
Linked list
 
IN C LANGUAGE- I've been trying to finish this program for the last fe.docx
IN C LANGUAGE- I've been trying to finish this program for the last fe.docxIN C LANGUAGE- I've been trying to finish this program for the last fe.docx
IN C LANGUAGE- I've been trying to finish this program for the last fe.docx
 
Data structure
Data  structureData  structure
Data structure
 
Sorting & Linked Lists
Sorting & Linked ListsSorting & Linked Lists
Sorting & Linked Lists
 
Linked list
Linked listLinked list
Linked list
 
Unit ii(dsc++)
Unit ii(dsc++)Unit ii(dsc++)
Unit ii(dsc++)
 
Chapter 5 ds
Chapter 5 dsChapter 5 ds
Chapter 5 ds
 
Linked List.ppt Linked List Datastructure concepts
Linked List.ppt Linked List Datastructure conceptsLinked List.ppt Linked List Datastructure concepts
Linked List.ppt Linked List Datastructure concepts
 
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjhlinked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
linked List.docx vhjgvjhvgjhjhbbjkhkjhkjh
 

Recently uploaded

DRUGS AND ITS classification slide share
DRUGS AND ITS classification slide shareDRUGS AND ITS classification slide share
DRUGS AND ITS classification slide share
taiba qazi
 
The basics of sentences session 6pptx.pptx
The basics of sentences session 6pptx.pptxThe basics of sentences session 6pptx.pptx
The basics of sentences session 6pptx.pptx
heathfieldcps1
 
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdfবাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
eBook.com.bd (প্রয়োজনীয় বাংলা বই)
 
Top five deadliest dog breeds in America
Top five deadliest dog breeds in AmericaTop five deadliest dog breeds in America
Top five deadliest dog breeds in America
Bisnar Chase Personal Injury Attorneys
 
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
IreneSebastianRueco1
 
Azure Interview Questions and Answers PDF By ScholarHat
Azure Interview Questions and Answers PDF By ScholarHatAzure Interview Questions and Answers PDF By ScholarHat
Azure Interview Questions and Answers PDF By ScholarHat
Scholarhat
 
Digital Artifact 1 - 10VCD Environments Unit
Digital Artifact 1 - 10VCD Environments UnitDigital Artifact 1 - 10VCD Environments Unit
Digital Artifact 1 - 10VCD Environments Unit
chanes7
 
Smart-Money for SMC traders good time and ICT
Smart-Money for SMC traders good time and ICTSmart-Money for SMC traders good time and ICT
Smart-Money for SMC traders good time and ICT
simonomuemu
 
A Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdfA Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdf
Jean Carlos Nunes Paixão
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
Peter Windle
 
MARY JANE WILSON, A “BOA MÃE” .
MARY JANE WILSON, A “BOA MÃE”           .MARY JANE WILSON, A “BOA MÃE”           .
MARY JANE WILSON, A “BOA MÃE” .
Colégio Santa Teresinha
 
PIMS Job Advertisement 2024.pdf Islamabad
PIMS Job Advertisement 2024.pdf IslamabadPIMS Job Advertisement 2024.pdf Islamabad
PIMS Job Advertisement 2024.pdf Islamabad
AyyanKhan40
 
Assessment and Planning in Educational technology.pptx
Assessment and Planning in Educational technology.pptxAssessment and Planning in Educational technology.pptx
Assessment and Planning in Educational technology.pptx
Kavitha Krishnan
 
The Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collectionThe Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collection
Israel Genealogy Research Association
 
Your Skill Boost Masterclass: Strategies for Effective Upskilling
Your Skill Boost Masterclass: Strategies for Effective UpskillingYour Skill Boost Masterclass: Strategies for Effective Upskilling
Your Skill Boost Masterclass: Strategies for Effective Upskilling
Excellence Foundation for South Sudan
 
Digital Artefact 1 - Tiny Home Environmental Design
Digital Artefact 1 - Tiny Home Environmental DesignDigital Artefact 1 - Tiny Home Environmental Design
Digital Artefact 1 - Tiny Home Environmental Design
amberjdewit93
 
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
National Information Standards Organization (NISO)
 
How to Fix the Import Error in the Odoo 17
How to Fix the Import Error in the Odoo 17How to Fix the Import Error in the Odoo 17
How to Fix the Import Error in the Odoo 17
Celine George
 
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Dr. Vinod Kumar Kanvaria
 
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
Nguyen Thanh Tu Collection
 

Recently uploaded (20)

DRUGS AND ITS classification slide share
DRUGS AND ITS classification slide shareDRUGS AND ITS classification slide share
DRUGS AND ITS classification slide share
 
The basics of sentences session 6pptx.pptx
The basics of sentences session 6pptx.pptxThe basics of sentences session 6pptx.pptx
The basics of sentences session 6pptx.pptx
 
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdfবাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
বাংলাদেশ অর্থনৈতিক সমীক্ষা (Economic Review) ২০২৪ UJS App.pdf
 
Top five deadliest dog breeds in America
Top five deadliest dog breeds in AmericaTop five deadliest dog breeds in America
Top five deadliest dog breeds in America
 
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
RPMS TEMPLATE FOR SCHOOL YEAR 2023-2024 FOR TEACHER 1 TO TEACHER 3
 
Azure Interview Questions and Answers PDF By ScholarHat
Azure Interview Questions and Answers PDF By ScholarHatAzure Interview Questions and Answers PDF By ScholarHat
Azure Interview Questions and Answers PDF By ScholarHat
 
Digital Artifact 1 - 10VCD Environments Unit
Digital Artifact 1 - 10VCD Environments UnitDigital Artifact 1 - 10VCD Environments Unit
Digital Artifact 1 - 10VCD Environments Unit
 
Smart-Money for SMC traders good time and ICT
Smart-Money for SMC traders good time and ICTSmart-Money for SMC traders good time and ICT
Smart-Money for SMC traders good time and ICT
 
A Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdfA Independência da América Espanhola LAPBOOK.pdf
A Independência da América Espanhola LAPBOOK.pdf
 
A Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in EducationA Strategic Approach: GenAI in Education
A Strategic Approach: GenAI in Education
 
MARY JANE WILSON, A “BOA MÃE” .
MARY JANE WILSON, A “BOA MÃE”           .MARY JANE WILSON, A “BOA MÃE”           .
MARY JANE WILSON, A “BOA MÃE” .
 
PIMS Job Advertisement 2024.pdf Islamabad
PIMS Job Advertisement 2024.pdf IslamabadPIMS Job Advertisement 2024.pdf Islamabad
PIMS Job Advertisement 2024.pdf Islamabad
 
Assessment and Planning in Educational technology.pptx
Assessment and Planning in Educational technology.pptxAssessment and Planning in Educational technology.pptx
Assessment and Planning in Educational technology.pptx
 
The Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collectionThe Diamonds of 2023-2024 in the IGRA collection
The Diamonds of 2023-2024 in the IGRA collection
 
Your Skill Boost Masterclass: Strategies for Effective Upskilling
Your Skill Boost Masterclass: Strategies for Effective UpskillingYour Skill Boost Masterclass: Strategies for Effective Upskilling
Your Skill Boost Masterclass: Strategies for Effective Upskilling
 
Digital Artefact 1 - Tiny Home Environmental Design
Digital Artefact 1 - Tiny Home Environmental DesignDigital Artefact 1 - Tiny Home Environmental Design
Digital Artefact 1 - Tiny Home Environmental Design
 
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
Pollock and Snow "DEIA in the Scholarly Landscape, Session One: Setting Expec...
 
How to Fix the Import Error in the Odoo 17
How to Fix the Import Error in the Odoo 17How to Fix the Import Error in the Odoo 17
How to Fix the Import Error in the Odoo 17
 
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
Exploiting Artificial Intelligence for Empowering Researchers and Faculty, In...
 
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
BÀI TẬP BỔ TRỢ TIẾNG ANH 8 CẢ NĂM - GLOBAL SUCCESS - NĂM HỌC 2023-2024 (CÓ FI...
 

08DsAlg.pdf

  • 1. 1 Data Structures and Algorithms ! The material for this lecture is drawn, in part, from! The Practice of Programming (Kernighan & Pike) Chapter 2! Jennifer Rexford !
  • 2. 2 Motivating Quotations! “Every program depends on algorithms and data structures, but few programs depend on the invention of brand new ones.”! -- Kernighan & Pike! “I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships.”! -- Linus Torvalds!
  • 3. 3 Goals of this Lecture! • Help you learn (or refresh your memory) about:! • Common data structures and algorithms! • Why? Shallow motivation:! • Provide examples of pointer-related C code! • Why? Deeper motivation:! • Common data structures and algorithms serve as “high level building blocks”! • A power programmer:! • Rarely creates programs from scratch! • Often creates programs using building blocks!
  • 4. 4 A Common Task! • Maintain a table of key/value pairs! • Each key is a string; each value is an int • Unknown number of key-value pairs! • Examples! • (student name, grade)! • (“john smith”, 84), (“jane doe”, 93), (“bill clinton”, 81)! • (baseball player, number)! • (“Ruth”, 3), (“Gehrig”, 4), (“Mantle”, 7)! • (variable name, value)! • (“maxLength”, 2000), (“i”, 7), (“j”, -10)! • For simplicity, allow duplicate keys (client responsibility)! • In Assignment #3, must check for duplicate keys!!
  • 5. 5 Data Structures and Algorithms! • Data structures! • Linked list of key/value pairs! • Hash table of key/value pairs! • Algorithms! • Create: Create the data structure! • Add: Add a key/value pair! • Search: Search for a key/value pair, by key! • Free: Free the data structure!
  • 6. 6 Data Structure #1: Linked List! • Data structure: Nodes; each contains key/value pair and pointer to next node! • Algorithms:! • Create: Allocate Table structure to point to first node! • Add: Insert new node at front of list! • Search: Linear search through the list! • Free: Free nodes while traversing; free Table structure! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle"
  • 7. 7 Linked List: Data Structure! struct Node { const char *key; int value; struct Node *next; }; struct Table { struct Node *first; }; 4 "Gehrig" 3 "Ruth" NULL struct! Table! struct! Node! struct! Node!
  • 8. 8 Linked List: Create (1)! t! struct Table *Table_create(void) { struct Table *t; t = (struct Table*) malloc(sizeof(struct Table)); t->first = NULL; return t; } struct Table *t; … t = Table_create(); …
  • 9. 9 Linked List: Create (2)! struct Table *Table_create(void) { struct Table *t; t = (struct Table*) malloc(sizeof(struct Table)); t->first = NULL; return t; } struct Table *t; … t = Table_create(); … t! NULL
  • 10. 10 Linked List: Add (1)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; p->value = value; p->next = t->first; t->first = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … These are pointers to! strings! 4 "Gehrig" 3 "Ruth" NULL t!
  • 11. 11 Linked List: Add (2)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; p->value = value; p->next = t->first; t->first = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … 4 "Gehrig" 3 "Ruth" NULL t! p!
  • 12. 12 Linked List: Add (3)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; p->value = value; p->next = t->first; t->first = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p!
  • 13. 13 Linked List: Add (4)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; p->value = value; p->next = t->first; t->first = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p!
  • 14. 14 Linked List: Add (5)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; p->value = value; p->next = t->first; t->first = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p!
  • 15. 15 Linked List: Search (1)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle"
  • 16. 16 Linked List: Search (2)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" p!
  • 17. 17 Linked List: Search (3)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" p!
  • 18. 18 Linked List: Search (4)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" p!
  • 19. 19 Linked List: Search (5)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" p!
  • 20. 20 Linked List: Search (6)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; for (p = t->first; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … t! 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" p! 4 1
  • 21. 21 Linked List: Free (1)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t!
  • 22. 22 Linked List: Free (2)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p!
  • 23. 23 Linked List: Free (3)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 24. 24 Linked List: Free (4)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 25. 25 Linked List: Free (5)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 26. 26 Linked List: Free (6)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 27. 27 Linked List: Free (7)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 28. 28 Linked List: Free (8)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 29. 29 Linked List: Free (9)! struct Table *t; … Table_free(t); … void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; for (p = t->first; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t) } 4 "Gehrig" 3 "Ruth" NULL 7 "Mantle" t! p! nextp!
  • 30. 30 Linked List Performance! • Create: !fast! • Add:! !fast! • Search: !slow! • Free: !slow! Would it be better to keep the nodes sorted by key?! What are the asymptotic run times (big-oh notation)?!
  • 31. 31 Data Structure #2: Hash Table! • Fixed-size array where each element points to a linked list! • Function maps each key to an array index ! • For example, for an integer key h • Hash function: i = h % ARRAYSIZE (mod function)! • Go to array element i, i.e., the linked list hashtab[i] • Search for element, add element, remove element, etc.! 0 ARRAYSIZE-1 struct Node *array[ARRAYSIZE];
  • 32. 32 Hash Table Example! • Integer keys, array of size 5 with hash function “h mod 5” ! • “1776 % 5” is 1! • “1861 % 5” is 1! • “1939 % 5” is 4! 1776 Revolution 1861 Civil 1939 WW2 0 1 2 3 4
  • 33. 33 How Large an Array?! • Large enough that average “bucket” size is 1! • Short buckets mean fast search! • Long buckets mean slow search! • Small enough to be memory efficient! • Not an excessive number of elements! • Fortunately, each array element is just storing a pointer! • This is OK:! 0 ARRAYSIZE-1
  • 34. 34 What Kind of Hash Function?! • Good at distributing elements across the array! • Distribute results over the range 0, 1, …, ARRAYSIZE-1! • Distribute results evenly to avoid very long buckets! • This is not so good:! 0 ARRAYSIZE-1 What would be the worst possible hash function?!
  • 35. 35 Hashing String Keys to Integers! • Simple schemes donʼt distribute the keys evenly enough! • Number of characters, mod ARRAYSIZE! • Sum the ASCII values of all characters, mod ARRAYSIZE! • …! • Hereʼs a reasonably good hash function! • Weighted sum of characters xi in the string! • (Σ aixi) mod ARRAYSIZE! • Best if a and ARRAYSIZE are relatively prime! • E.g., a = 65599, ARRAYSIZE = 1024!
  • 36. 36 Implementing Hash Function! • Potentially expensive to compute ai for each value of i! • Computing ai for each value of I! • Instead, do (((x[0] * 65599 + x[1]) * 65599 + x[2]) * 65599 + x[3]) * …! unsigned int hash(const char *x) { int i; unsigned int h = 0U; for (i=0; x[i]!='0'; i++) h = h * 65599 + (unsigned char)x[i]; return h % 1024; } Can be more clever than this for powers of two!! (Described in Appendix)!
  • 37. 37 Hash Table Example! Example: ARRAYSIZE = 7! Lookup (and enter, if not present) these strings: the, cat, in, the, hat! Hash table initially empty.! First word: the. hash(“the”) = 965156977. 965156977 % 7 = 1.! Search the linked list table[1] for the string “the”; not found.! 0 1 2 3 4 5 6
  • 38. 38 Hash Table Example (cont.)! Example: ARRAYSIZE = 7! Lookup (and enter, if not present) these strings: the, cat, in, the, hat! Hash table initially empty.! First word: “the”. hash(“the”) = 965156977. 965156977 % 7 = 1.! Search the linked list table[1] for the string “the”; not found! Now: table[1] = makelink(key, value, table[1])! 0 1 2 3 4 5 6 the
  • 39. 39 Hash Table Example (cont.)! Second word: “cat”. hash(“cat”) = 3895848756. 3895848756 % 7 = 2.! Search the linked list table[2] for the string “cat”; not found! Now: table[2] = makelink(key, value, table[2])! 0 1 2 3 4 5 6 the
  • 40. 40 Hash Table Example (cont.)! Third word: “in”. hash(“in”) = 6888005. 6888005% 7 = 5.! Search the linked list table[5] for the string “in”; not found! Now: table[5] = makelink(key, value, table[5])! 0 1 2 3 4 5 6 the cat
  • 41. 41 Hash Table Example (cont.)! Fourth word: “the”. hash(“the”) = 965156977. 965156977 % 7 = 1.! Search the linked list table[1] for the string “the”; found it!! 0 1 2 3 4 5 6 the cat in
  • 42. 42 Hash Table Example (cont.)! Fourth word: “hat”. hash(“hat”) = 865559739. 865559739 % 7 = 2.! Search the linked list table[2] for the string “hat”; not found.! Now, insert “hat” into the linked list table[2]. ! At beginning or end? Doesnʼt matter.! 0 1 2 3 4 5 6 the cat in
  • 43. 43 Hash Table Example (cont.)! Inserting at the front is easier, so add “hat” at the front ! 0 1 2 3 4 5 6 the hat in cat
  • 44. 44 Hash Table: Data Structure! enum {BUCKET_COUNT = 1024}; struct Node { const char *key; int value; struct Node *next; }; struct Table { struct Node *array[BUCKET_COUNT]; }; NULL 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … struct! Table! struct! Node! struct! Node!
  • 45. 45 Hash Table: Create! struct Table *Table_create(void) { struct Table *t; t = (struct Table*)calloc(1, sizeof(struct Table)); return t; } struct Table *t; … t = Table_create(); … t! NULL NULL NULL 0 1 1023 …
  • 46. 46 Hash Table: Add (1)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); int h = hash(key); p->key = key; p->value = value; p->next = t->array[h]; t->array[h] = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … t! NULL 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … These are pointers to strings! Pretend that “Ruth”! hashed to 23 and! “Gehrig” to 723!
  • 47. 47 Hash Table: Add (2)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); int h = hash(key); p->key = key; p->value = value; p->next = t->array[h]; t->array[h] = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … t! NULL 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … p!
  • 48. 48 Hash Table: Add (3)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); int h = hash(key); p->key = key; p->value = value; p->next = t->array[h]; t->array[h] = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … t! NULL 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … 7 "Mantle" p! Pretend that “Mantle”! hashed to 806, and so! h = 806!
  • 49. 49 Hash Table: Add (4)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); int h = hash(key); p->key = key; p->value = value; p->next = t->array[h]; t->array[h] = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … t! NULL 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … 7 "Mantle" NULL p! h = 806!
  • 50. 50 Hash Table: Add (5)! void Table_add(struct Table *t, const char *key, int value) { struct Node *p = (struct Node*)malloc(sizeof(struct Node)); int h = hash(key); p->key = key; p->value = value; p->next = t->array[h]; t->array[h] = p; } struct Table *t; … Table_add(t, "Ruth", 3); Table_add(t, "Gehrig", 4); Table_add(t, "Mantle", 7); … t! 4 "Gehrig" NULL 3 "Ruth" NULL NULL NULL 0 1 806 23 723 … … … NULL 1023 … 7 "Mantle" NULL p! h = 806!
  • 51. 51 Hash Table: Search (1)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); for (p = t->array[h]; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … …
  • 52. 52 Hash Table: Search (2)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); for (p = t->array[h]; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … Pretend that “Gehrig”! hashed to 723, and so! h = 723!
  • 53. 53 Hash Table: Search (3)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); for (p = t->array[h]; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … h = 723! p!
  • 54. 54 Hash Table: Search (4)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); for (p = t->array[h]; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … h = 723! p!
  • 55. 55 Hash Table: Search (5)! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); for (p = t->array[h]; p != NULL; p = p->next) if (strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } struct Table *t; int value; int found; … found = Table_search(t, "Gehrig", &value); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … h = 723! p! 4 1
  • 56. 56 Hash Table: Free (1)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … …
  • 57. 57 Hash Table: Free (2)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 0!
  • 58. 58 Hash Table: Free (3)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 0! p!
  • 59. 59 Hash Table: Free (4)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 1, …, 23! p!
  • 60. 60 Hash Table: Free (5)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 23! p!
  • 61. 61 Hash Table: Free (6)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 23! p! nextp!
  • 62. 62 Hash Table: Free (7)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 23! p! nextp!
  • 63. 63 Hash Table: Free (8)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 24, …, 723! b = 724, …, 806! b = 807, …, 1024!
  • 64. 64 Hash Table: Free (9)! void Table_free(struct Table *t) { struct Node *p; struct Node *nextp; int b; for (b = 0; b < BUCKET_COUNT; b++) for (p = t->array[b]; p != NULL; p = nextp) { nextp = p->next; free(p); } free(t); } struct Table *t; … Table_free(t); … … t! 4 "Gehrig" NULL 3 "Ruth" NULL 7 "Mantle" NULL … NULL NULL 0 1 806 23 723 … NULL 1023 … … b = 1024!
  • 65. 65 Hash Table Performance! • Create: !fast! • Add: !fast! • Search: !fast! • Free: !slow! What are the asymptotic run times (big-oh notation)?! Is hash table search always fast?!
  • 66. 66 Key Ownership! • Note: Table_add() functions contain this code:! • Caller passes key, which is a pointer to memory where a string resides! • Table_add() function stores within the table the address where the string resides! void Table_add(struct Table *t, const char *key, int value) { … struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = key; … }
  • 67. 67 Key Ownership (cont.)! • Problem: Consider this calling code:! struct Table t; char k[100] = "Ruth"; … Table_add(t, k, 3); strcpy(k, "Gehrig"); … • Via Table_add(), table contains memory address k! • Client changes string at memory address k! • Thus client changes key within table! What happens if the client searches t for “Ruth”?! What happens if the client searches t for “Gehrig”?!
  • 68. 68 Key Ownership (cont.)! • Solution: Table_add() saves copy of given key! • If client changes string at memory address k, data structure is not affected! • Then the data structure “owns” the copy, that is:! • The data structure is responsible for freeing the memory in which the copy resides! • The Table_free() function must free the copy! void Table_add(struct Table *t, const char *key, int value) { … struct Node *p = (struct Node*)malloc(sizeof(struct Node)); p->key = (const char*)malloc(strlen(key) + 1); strcpy(p->key, key); … } Why add 1?!
  • 69. 69 Summary! • Common data structures & associated algorithms! • Linked list! • Fast insert, slow search! • Hash table! • Fast insert, (potentially) fast search! • Invaluable for storing key/value pairs! • Very common! • Related issues! • Hashing algorithms! • Memory ownership!
  • 70. 70 Appendix! • “Stupid programmer tricks” related to hash tables…!
  • 71. 71 Revisiting Hash Functions! • Potentially expensive to compute “mod c”! • Involves division by c and keeping the remainder! • Easier when c is a power of 2 (e.g., 16 = 24)! • An alternative (by example)! • 53 = 32 + 16 + 4 + 1! • 53 % 16 is 5, the last four bits of the number! • Would like an easy way to isolate the last four bits… ! 0 0 1 1 0 1 0 1 1 2 4 8 16 32 0 0 0 0 0 1 0 1 1 2 4 8 16 32
  • 72. 72 Recall: Bitwise Operators in C! • Bitwise AND (&)! • Mod on the cheap!! • E.g., h = 53 & 15;! • Bitwise OR (|)! & 0 1 0 1 0 0 0 1 | 0 1 0 1 0 1 1 1 0 0 1 1 0 1 0 1 0 0 0 0 1 1 1 1 53 & 15 0 0 0 0 0 1 0 1 5 • Oneʼs complement (~)! • Turns 0 to 1, and 1 to 0! • E.g., set last three bits to 0! • x = x & ~7;!
  • 73. 73 A Faster Hash Function! unsigned int hash(const char *x) { int i; unsigned int h = 0U; for (i=0; x[i]!='0'; i++) h = h * 65599 + (unsigned char)x[i]; return h % 1024; } unsigned int hash(const char *x) { int i; unsigned int h = 0U; for (i=0; x[i]!='0'; i++) h = h * 65599 + (unsigned char)x[i]; return h & 1023; } Faster! Previous! version! What happens if you mistakenly write “h & 1024”?!
  • 74. 74 Speeding Up Key Comparisons! • Speeding up key comparisons! • For any non-trivial value comparison function! • Trick: store full hash result in structure! int Table_search(struct Table *t, const char *key, int *value) { struct Node *p; int h = hash(key); /* No % in hash function */ for (p = t->array[h%1024]; p != NULL; p = p->next) if ((p->hash == h) && strcmp(p->key, key) == 0) { *value = p->value; return 1; } return 0; } Why is this so much faster?!