Joseph Haugh
University of New Mexico
What is the purpose of the malloc
function in C?
What is the purpose of the malloc
function in C?
Which operator is used to access the members of a struct through a pointer?
Which operator is used to access the members of a struct through a pointer?
What is the time complexity of inserting a node at the beginning of a singly linked list?
What is the time complexity of inserting a node at the beginning of a singly linked list?
What happens if you try to access memory that has already been freed using free?
What happens if you try to access memory that has already been freed using free?
What is the output of the following code snippet?
int x = 5;
int *p = &x;
printf("%d", *p);
5
struct Person {
char name[20];
int age;
};
struct Person p1 = {"John", 25};
printf("%s", p1.name);
John
int *p = (int *)malloc(sizeof(int));
*p = 10;
printf("%d", *p);
free(p);
10
struct Node {
int data;
struct Node *next;
};
struct Node *head = NULL;
printf("%p", head);
(nil)
int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
printf("%d", *(ptr + 2));
3
char str[] = "Hello";
char *ptr = str;
ptr++;
printf("%c", *ptr);
e
int x = 10;
int y = 20;
int *ptr1 = &x;
int *ptr2 = &y;
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
printf("%d %d", x, y);
20 10
struct Point {
int x;
int y;
};
struct Point p1 = {1, 2};
struct Point *ptr = &p1;
printf("%d", ptr->y);
2
int *ptr = (int *)malloc(5 * sizeof(int));
for (int i = 0; i < 5; i++) {
*(ptr + i) = i;
}
printf("%d", *(ptr + 3));
free(ptr);
3
struct Node {
int data;
struct Node *next;
};
struct Node *head = NULL;
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
new_node->data = 5;
new_node->next = NULL;
head = new_node;
printf("%d", head->data);
5
Read a file and count the occurrences of each word.
now is the time for all good men to come to the aid of their party
If a node were added with the word “hello”, where would it be placed?
The structure, tnode, is used for each node of the binary tree.
struct tnode {
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
This is called a self-referential structure since it contains pointers to other tnodes.
An instance of this struct allocates space for a pointer to a char array, an int, and two pointers to other tnodes. On my 64-bit address machine, this is a total of 8 + 4 + 8 + 8 = 28 bytes.
Allocate memory for a tree node.
In this binary tree, nodes are added to leaves. Thus, initialize the node’s children to NULL.
Call strCopyMalloc to allocate space for the word and to copy it from the input buffer into the allocated space.
struct tnode *talloc(char *newWord) {
struct tnode *node = malloc(sizeof(struct tnode));
node->word = strCopyMalloc(newWord);
node->left = NULL;
node->right = NULL;
node->count = 1;
return node;
}
Allocated memory for a copy of newWord.
Copy each character from newWord into the allocated block.
Return a pointer to the start of the allocated block.
char *strCopyMalloc(char *source) {
char *sink;
sink = malloc(strlen(source) + 1);
if (sink != NULL) strcpy(sink, source);
return sink;
}
In Kernighan and Ritchie’s binary tree, memory is allocated and never freed!
MEMORY LEAK WARNING: DO NOT free a node until:
Its children have been freed, or pointers to its children have been saved somewhere else.
Its word has been freed.
struct tnode *root;
root = talloc("Memory");
root->right = talloc("Leak");
root->left = talloc("Bad");
free(root); /* Leaves "unreachable" memory. */
Recursive function that frees all allocated memory in a subtree.
void freeSubtree(struct tnode *node) {
if (node == NULL) return;
freeSubtree(node->left);
freeSubtree(node->right);
free(node->word);
free(node);
}
Any references to node (such as would be in node’s parent) MUST NOT BE USED AFTER calling this. Best practice is to set such references to NULL.
This main() demonstrates usage and offers a simple test of creating, setting, printing, and freeing tnode.
void main(void) {
struct tnode *root;
root = talloc("geralt");
root->left = talloc("ciri");
root->right = talloc("yen");
printf("node: %s (L)=%s, (R)=%s\n", root->word,
root->left->word, root->right->word);
freeSubtree(root);
root = NULL; /* "Best practice" */
}
Pre-Order: Root, then children:
now is for all aid come good men the of party time their to
In-Order: Left, root, right:
aid all come for good is men now of party the their time to
Post-Order: Children, then root:
aid come all good for men is party of their to time the now
Breadth-first: One level at a time:
now is the for men of time all good party their to aid come
void treeprint(struct tnode *node)
{
if(node != NULL)
{
treeprint(node->left);
printf("%4d %s\n", node->count, node->word);
treeprint(node->right);
}
}
What sort of traversal happens here?
How could we traverse the tree in a different order?
Create a queue to hold tree nodes
Add root node to the queue
While queue is not empty:
A queue is a FIFO structure. How might we implement it?
A stack is a LIFO structure. What would happen if we replaced the queue with a stack?