C
basic linked list
#include <stddef.h>
#include <stdio.h>
typedef struct Node {
int value;
struct Node *next;
} node_t;
void push_end(node_t *head, node_t *next) {
node_t *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = next;
}
int main() {
node_t head;
node_t one = {1, NULL};
node_t two = {2, NULL};
push_end(&head, &one);
push_end(&head, &two);
node_t *current = &head;
while (current->next != NULL) {
current = current->next;
printf("%d\n", current->value);
}
}
I’ll leave the above for reference, but it kinda sucks because all your nodes have to already exist in the one function.
So here’s a better one using malloc to create nodes on the heap:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct Data {
int x;
} data_t;
typedef struct Node {
data_t data;
struct Node *next;
} node_t;
node_t *create_node(data_t data){
node_t *new_node = malloc(sizeof(node_t));
new_node->data = data;
new_node->next = NULL;
return new_node;
}
void destroy_list(node_t *head){
node_t *next;
for (node_t *current = head; current != NULL; current = next) {
next = current->next;
free(current);
}
}
node_t* push_end(node_t *head, data_t next) {
node_t *new_node = create_node(next);
node_t *current;
if (head==NULL) {
head = new_node;
} else {
for (current = head; current->next != NULL; current = current->next) {
;
}
current->next = new_node;
}
return head;
}
node_t *reverse_list(node_t *head ) {
node_t *prev = NULL;
node_t *next;
for (node_t *curr = head; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
void print_list(node_t *head) {
for (node_t *current = head; current != NULL; current = current->next) {
printf("%d\n", current->data.x);
}
}
int main() {
node_t *my_list = NULL;
for (int i=1; i<10; i++) {
data_t d = {i};
my_list = push_end(my_list, d);
}
print_list(my_list);
printf("\n");
my_list = reverse_list(my_list);
print_list(my_list);
destroy_list(my_list);
}
Trees
Trees contain layers of branches, which contains nodes, which contain data.
For example:
from random import randint
def random_branch():
return [randint(1, 9) for _ in range(3)]
tree = [[[random_branch(), random_branch()]]]
depth = 3
for _ in range(depth):
new_layer = []
for branches in tree[-1]:
for branch in branches:
new_branch = []
for node in branch:
new_branch.append(random_branch())
new_layer.append(new_branch)
tree.append(new_layer)
for layer in tree:
print(layer)
print()
To walk back up the tree, nodes can contain their parent’s node in addition to their data.
from random import randint
class Node:
def __init__(self, data, parent=None):
self.data = data
self.parent = parent
def random_branch(parent):
return [Node(randint(1, 9), parent) for _ in range(3)]
tree = [[[random_branch(None), random_branch(None)]]]
depth = 3
for _ in range(depth):
new_layer = []
for branches in tree[-1]:
for branch in branches:
new_branch = []
for node in branch:
new_branch.append(random_branch(parent=node))
new_layer.append(new_branch)
tree.append(new_layer)
for layer in tree:
print([[[node.data for node in branch] for branch in branches] for branches in layer])
print()
def walk_up_tree(node):
path = []
current = node
while current is not None:
path.append(current)
current = current.parent
return path[::-1]
bottom_node = tree[-1][0][0][0] # arbitrary example
print(bottom_node.data)
path = walk_up_tree(bottom_node)
print([node.data for node in path])
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
typedef struct Data {
int x;
} data_t;
typedef struct TreeNode {
data_t data;
struct TreeNode *parent;
} treenode_t;
typedef struct TreeListNode {
treenode_t *treenode;
struct TreeListNode *next;
} treelistnode_t;
treelistnode_t *create_treelist_node(treenode_t *treenode){
treelistnode_t *new_node = malloc(sizeof(treelistnode_t));
new_node->treenode = treenode;
new_node->next = NULL;
return new_node;
}
treenode_t *treenode_create(data_t data, treenode_t *parent){
treenode_t *new_node = malloc(sizeof(treenode_t));
new_node->data = data;
new_node->parent = parent;
return new_node;
}
treenode_t *treenode_copy(treenode_t *original){
assert(original!=NULL);
treenode_t *copy = malloc(sizeof(treenode_t));
copy->data = original->data;
copy->parent = original->parent;
return copy;
}
treelistnode_t* treelist_push_end(treelistnode_t *head, treenode_t *next) {
treelistnode_t *new_node = create_treelist_node(next);
treelistnode_t *current;
if (head==NULL) {
head = new_node;
} else {
for (current = head; current->next != NULL; current = current->next) {
;
}
current->next = new_node;
}
return head;
}
treelistnode_t *add_random_branch(treelistnode_t *tree, treenode_t *parent) {
data_t d1 = {rand() % 10};
data_t d2 = {rand() % 10};
data_t d3 = {rand() % 10};
treenode_t *r1 = treenode_create(d1, parent);
treenode_t *r2 = treenode_create(d2, parent);
treenode_t *r3 = treenode_create(d3, parent);
tree = treelist_push_end(tree, r1);
tree = treelist_push_end(tree, r2);
tree = treelist_push_end(tree, r3);
return tree;
}
void treelist_free(treelistnode_t *head){
treelistnode_t *next;
for (treelistnode_t *current = head; current != NULL; current = next) {
next = current->next;
free(current->treenode);
free(current);
}
}
treelistnode_t *treelist_reverse(treelistnode_t *head) {
treelistnode_t *prev = NULL;
treelistnode_t *next;
for (treelistnode_t *curr = head; curr != NULL; curr = next) {
next = curr->next;
curr->next = prev;
prev = curr;
}
return prev;
}
int treelist_length(treelistnode_t *head) {
treelistnode_t *current;
int length = 0;
for (current = head; current != NULL; current = current->next) {
length += 1;
}
return length;
}
treelistnode_t *walk_up_tree(treenode_t *node) {
treelistnode_t *path = NULL;
for (treenode_t* current = node; current != NULL; current = current->parent) {
path = treelist_push_end(path, treenode_copy(current));
}
path = treelist_reverse(path);
return path;
}
treelistnode_t *treelist_copy(treelistnode_t *head){
treelistnode_t *ret = NULL;
for (treelistnode_t* current = head; current != NULL; current = current->next) {
ret = treelist_push_end(ret, treenode_copy(current->treenode));
}
return ret;
}
treelistnode_t *tree_get_max(treelistnode_t *head) {
// max depth prioritised first, max data prioritised second
// assumes the tree nodes are ordered by depth already
// returns a path from the root
int x;
int best_x = 0;
int depth;
int best_depth = 0;
treelistnode_t *ret = NULL;
treelistnode_t *current;
treelistnode_t *path;
for (current = head; current != NULL; current = current->next) {
x = current->treenode->data.x;
path = walk_up_tree(current->treenode);
depth = treelist_length(path);
if (depth > best_depth) {
best_x = x; // prioritise depth more than x
}
if (depth >= best_depth) {
if (x > best_x) {
treelist_free(ret);
ret = treelist_copy(path);
best_x = x;
}
best_depth = depth;
}
treelist_free(path);
}
assert(ret != NULL);
return ret;
}
int main() {
treelistnode_t *current;
treelistnode_t *next;
treelistnode_t *tree = NULL;
treelistnode_t *to_push;
data_t d1 = {111};
data_t d2 = {222};
treenode_t *r1 = treenode_create(d1, NULL);
treenode_t *r2 = treenode_create(d2, NULL);
tree = treelist_push_end(tree, r1);
tree = treelist_push_end(tree, r2);
int max_depth = 2;
for (int d=0; d<max_depth; d++) {
printf("depth %d\n", d);
to_push = NULL;
for (current = tree; current != NULL; current = next) {
next = current->next;
to_push = add_random_branch(to_push, current->treenode);
}
for (current = to_push; current != NULL; current = current->next) {
printf("%d\n", current->treenode->data.x);
tree = treelist_push_end(tree, treenode_copy(current->treenode));
}
treelist_free(to_push);
}
treelistnode_t *max = tree_get_max(tree);
printf("max path: ");
for (current = max; current != NULL; current = current->next) {
printf("%d ", current->treenode->data.x);
}
treelist_free(max);
treelist_free(tree);
return 0;
}
TCP Client
Let’s write some code to replicate this functionality:
$ printf "HEAD / HTTP/1.0\n\n" | nc www.google.com 80
HTTP/1.0 200 OK
Content-Type: text/html; charset=ISO-8859-1
Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-XTpTnaBEuxqhU5t0SKJYTQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Date: ...
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Expires: ...
Cache-Control: private
Set-Cookie: ...
Set-Cookie: ...
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define IP "142.251.221.78" // www.google.com
#define PORT 80 // http
int main() {
int s;
char* data;
char buf[512];
struct sockaddr_in sock;
sock.sin_addr.s_addr = inet_addr(IP);
sock.sin_port = htons(PORT);
sock.sin_family = AF_INET;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s<0) {
printf("socket() error\n");
return -1;
}
if (connect(s, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)) != 0) {
printf("connect() error\n");
close(s);
return -1;
}
data = "HEAD / HTTP/1.0\n\n";
write(s, data, strlen(data));
read(s, buf, 511);
printf("%s", buf);
close(s);
return 0;
}