Compare commits
10 Commits
0c711115df
...
52dd7164c5
Author | SHA1 | Date |
---|---|---|
|
52dd7164c5 | |
|
b63d729b87 | |
|
3644c63f43 | |
|
9b53857a64 | |
|
213242a4eb | |
|
440586dea0 | |
|
bed65ad722 | |
|
755f16877d | |
|
351db3f366 | |
|
fe6ba5fa8b |
163
c/arraylist.c
163
c/arraylist.c
|
@ -1,24 +1,29 @@
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
typedef struct ArrayList {
|
typedef struct i32_ArrayList {
|
||||||
int capacity;
|
int capacity; // capacity of the array
|
||||||
int index;
|
int index; // the current location the list that is to be written to
|
||||||
int data[];
|
int32_t data[]; // the data
|
||||||
} ArrayList;
|
} i32_ArrayList;
|
||||||
|
|
||||||
|
i32_ArrayList* new_arraylist(int cap) {
|
||||||
|
i32_ArrayList* arr = malloc(sizeof(i32_ArrayList) + cap * sizeof(int));
|
||||||
|
|
||||||
|
if (arr == NULL) {
|
||||||
|
printf("ERROR: there was an error attemping to allocate memory for i32_ArrayList\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
ArrayList* new_arraylist(int cap) {
|
|
||||||
ArrayList* arr = malloc(sizeof(ArrayList) + cap * sizeof(int));
|
|
||||||
arr->capacity = cap;
|
arr->capacity = cap;
|
||||||
arr->index = 0;
|
arr->index = 0;
|
||||||
for (int i = 0; i < cap; i++) {
|
|
||||||
arr->data[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_to_array(ArrayList* s, int v) {
|
// add to end of the array
|
||||||
|
void array_append(i32_ArrayList* s, int v) {
|
||||||
if (s->index == s->capacity) {
|
if (s->index == s->capacity) {
|
||||||
printf("you attempted to insert %d, but array is at capacity cannot add mode values\n", v);
|
printf("you attempted to insert %d, but array is at capacity cannot add mode values\n", v);
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,35 +32,141 @@ void push_to_array(ArrayList* s, int v) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_from_array(ArrayList* s) {
|
void resize_arraylist(i32_ArrayList** arr) {
|
||||||
|
int new_size = (*arr)->capacity * 2;
|
||||||
|
i32_ArrayList* new_arr = realloc((*arr), (sizeof(int) * new_size) + sizeof(i32_ArrayList));
|
||||||
|
|
||||||
|
if (new_arr == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: unable to resize array\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
(*arr) = new_arr;
|
||||||
|
(*arr)->capacity = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void array_append2(i32_ArrayList* arr, int v) {
|
||||||
|
if (arr->index == arr->capacity) {
|
||||||
|
// lets just double the capacity
|
||||||
|
resize_arraylist(&arr);
|
||||||
|
printf("size of arr: %d\n", arr->capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_append(arr, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an array list and fill in with values from array
|
||||||
|
i32_ArrayList* new_arraylist_from_array(int cap, int* arr) {
|
||||||
|
i32_ArrayList* out = new_arraylist(cap);
|
||||||
|
for (int i = 0; i < cap; i++) {
|
||||||
|
array_append(out, arr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert value at index
|
||||||
|
// the strategy here is to start from the last element in the array and shift it to the right
|
||||||
|
// gotta be careful and check that the index + 1 <= capacity otherwise we are in trouble
|
||||||
|
void array_insert_at(i32_ArrayList* arr, int at_index, int32_t value) {
|
||||||
|
if (at_index == arr->index) {
|
||||||
|
array_append(arr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (at_index + 1 > arr->capacity) {
|
||||||
|
printf("ERROR: this insert is not possible since the shift required would be over the capacity of the array\n");
|
||||||
|
printf("You requested insert at %d but array capacity is set to %d\n", at_index, arr->capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = arr->index; i >= at_index; i--) {
|
||||||
|
arr->data[i + 1] = arr->data[i];
|
||||||
|
}
|
||||||
|
arr->data[at_index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t array_get_at(i32_ArrayList* arr, int index) {
|
||||||
|
return (arr->data[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t pop_from_array(i32_ArrayList* s) {
|
||||||
if (s->index == 0) {
|
if (s->index == 0) {
|
||||||
printf("there is nothing to remove!\n");
|
printf("there is nothing to remove!\n");
|
||||||
|
return (-99);
|
||||||
} else {
|
} else {
|
||||||
|
int32_t val = s->data[s->index - 1];
|
||||||
s->index--;
|
s->index--;
|
||||||
|
|
||||||
|
return (val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void grow_array_list(ArrayList* s, int amount) {
|
void grow_array_list(i32_ArrayList* s, int amount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_array_list(ArrayList* arr) {
|
void print_array_list(i32_ArrayList* arr) {
|
||||||
printf("[");
|
printf("[");
|
||||||
for (int i = 0; i < arr->index; i++) {
|
for (int i = 0; i < arr->index; i++) {
|
||||||
printf(" %d ", arr->data[i]);
|
printf(" %d ", arr->data[i]);
|
||||||
}
|
}
|
||||||
printf("]\n");
|
printf("]\t<capacity: %d; index: %d>\n", arr->capacity, arr->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ArrayList* a = new_arraylist(5);
|
i32_ArrayList* a = new_arraylist(5);
|
||||||
push_to_array(a, 10);
|
int arr_values[5] = {1, 2, 3, 4, 5};
|
||||||
push_to_array(a, 11);
|
i32_ArrayList* b = new_arraylist_from_array(5, arr_values);
|
||||||
push_to_array(a, 12);
|
print_array_list(b);
|
||||||
push_to_array(a, 12);
|
|
||||||
push_to_array(a, 12);
|
// these should all work just fine
|
||||||
push_to_array(a, 12);
|
array_append(a, 10);
|
||||||
push_to_array(a, 12);
|
|
||||||
pop_from_array(a);
|
|
||||||
push_to_array(a, 155);
|
|
||||||
print_array_list(a);
|
print_array_list(a);
|
||||||
}
|
array_append(a, 11);
|
||||||
|
print_array_list(a);
|
||||||
|
array_append(a, 12);
|
||||||
|
print_array_list(a);
|
||||||
|
array_append(a, 13);
|
||||||
|
print_array_list(a);
|
||||||
|
array_append(a, 14);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// this one will error
|
||||||
|
array_append(a, 100);
|
||||||
|
|
||||||
|
// so we remove one and then add
|
||||||
|
pop_from_array(a);
|
||||||
|
print_array_list(a);
|
||||||
|
array_append(a, 100);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// now we test inserting different index
|
||||||
|
array_insert_at(a, 3, 55);
|
||||||
|
print_array_list(a);
|
||||||
|
array_insert_at(a, 4, 555);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// what happens if try to insert at the last element
|
||||||
|
// this first implementation of the araylist will just overwrite this value
|
||||||
|
array_insert_at(a, 4, 100);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// what if insert at 3 in this first version?
|
||||||
|
// this will shift the current 3 to 4, but this causes the 100 to be removed
|
||||||
|
array_insert_at(a, 3, 123);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// lets implement v2 versions of these function that will grow
|
||||||
|
// the array when required
|
||||||
|
array_append2(a, 5656);
|
||||||
|
print_array_list(a);
|
||||||
|
|
||||||
|
// array_append(a, 14);
|
||||||
|
// print_array_list(a);
|
||||||
|
// pop_from_array(a);
|
||||||
|
// print_array_list(a);
|
||||||
|
// array_insert_at(a, 5, 90000);
|
||||||
|
// print_array_list(a);
|
||||||
|
// array_insert_at(a, 3, 1000);
|
||||||
|
// array_insert_at(a, 4, 1000);
|
||||||
|
// array_insert_at(a, 5, 10001);
|
||||||
|
// print_array_list(a);
|
||||||
|
}
|
||||||
|
|
|
@ -167,6 +167,22 @@ void print_stack(Stack* stack) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_stack_v2(Stack* stack) {
|
||||||
|
if (stack->len == 0) {
|
||||||
|
printf("ERROR: empty stack\n");
|
||||||
|
} else {
|
||||||
|
printf("[ ");
|
||||||
|
int counter = 0;
|
||||||
|
Node* curr = stack->head;
|
||||||
|
while (counter < stack->len) {
|
||||||
|
printf("%d ", curr->value);
|
||||||
|
curr = curr->prev;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
printf(" ]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
/* lets create the following tree
|
/* lets create the following tree
|
||||||
12
|
12
|
||||||
|
@ -192,10 +208,12 @@ int main() {
|
||||||
walk_tree_post_order(root_node, post_stack);
|
walk_tree_post_order(root_node, post_stack);
|
||||||
walk_tree_in_order(root_node, in_order_stack);
|
walk_tree_in_order(root_node, in_order_stack);
|
||||||
|
|
||||||
printf("the len of the stack is %d\n", stack->len);
|
printf("pre order: ", stack->len);
|
||||||
print_stack(stack);
|
print_stack_v2(stack);
|
||||||
print_stack(post_stack);
|
printf("in order: ", stack->len);
|
||||||
print_stack(in_order_stack);
|
print_stack_v2(post_stack);
|
||||||
|
printf("post order: ", stack->len);
|
||||||
|
print_stack_v2(in_order_stack);
|
||||||
free(stack);
|
free(stack);
|
||||||
free(post_stack);
|
free(post_stack);
|
||||||
free(in_order_stack);
|
free(in_order_stack);
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct TreeNode {
|
||||||
|
int value;
|
||||||
|
struct TreeNode* left;
|
||||||
|
struct TreeNode* right;
|
||||||
|
} TreeNode;
|
||||||
|
|
||||||
|
typedef struct Tree {
|
||||||
|
TreeNode* root;
|
||||||
|
} Tree;
|
||||||
|
|
||||||
|
/* Set up data structures to be able to support the breadth first search of a tree */
|
||||||
|
typedef struct QNode {
|
||||||
|
TreeNode* tnode; // this is the value of the QNode
|
||||||
|
struct QNode* next;
|
||||||
|
} QNode;
|
||||||
|
|
||||||
|
typedef struct Q {
|
||||||
|
QNode* head;
|
||||||
|
QNode* tail;
|
||||||
|
int length;
|
||||||
|
} Q;
|
||||||
|
|
||||||
|
TreeNode* new_tree_node(int value) {
|
||||||
|
TreeNode* node = malloc(sizeof(TreeNode));
|
||||||
|
node->left = NULL;
|
||||||
|
node->right = NULL;
|
||||||
|
node->value = value;
|
||||||
|
|
||||||
|
return (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
QNode* new_qnode(TreeNode* tnode) {
|
||||||
|
QNode* node = malloc(sizeof(QNode));
|
||||||
|
node->next = NULL;
|
||||||
|
node->tnode = tnode;
|
||||||
|
|
||||||
|
return (node);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tree* new_tree(TreeNode* root) {
|
||||||
|
Tree* tree = malloc(sizeof(Tree));
|
||||||
|
tree->root = root;
|
||||||
|
return (tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q* new_Q() {
|
||||||
|
Q* q = malloc(sizeof(Q));
|
||||||
|
q->head = NULL;
|
||||||
|
q->tail = NULL;
|
||||||
|
q->length = 0;
|
||||||
|
|
||||||
|
return (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_child_left(TreeNode* parent, TreeNode* node) {
|
||||||
|
if (parent->left != NULL) {
|
||||||
|
printf("ERROR: left child is non-empty\n");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
parent->left = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_child_right(TreeNode* parent, TreeNode* node) {
|
||||||
|
if (parent->right != NULL) {
|
||||||
|
printf("ERROR: right child is non-empty\n");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
parent->right = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// always add at tail
|
||||||
|
void q_add_node(Q* q, QNode* node) {
|
||||||
|
if (q->length == 0) {
|
||||||
|
q->head = node;
|
||||||
|
q->tail = node;
|
||||||
|
q->length++;
|
||||||
|
} else {
|
||||||
|
q->tail->next = node;
|
||||||
|
q->tail = node;
|
||||||
|
q->length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// always remove from head
|
||||||
|
TreeNode* q_remove_node(Q* q) {
|
||||||
|
QNode* n = q->head;
|
||||||
|
TreeNode* tnode_at_head = n->tnode;
|
||||||
|
q->head = n->next;
|
||||||
|
q->length--;
|
||||||
|
free(n);
|
||||||
|
return (tnode_at_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
[10, 5, 7, 12, 8, 88, 14]
|
||||||
|
|
||||||
|
10
|
||||||
|
5 7
|
||||||
|
12 8 88 14
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool bf_search(Tree tree, int value) {
|
||||||
|
// start by adding th eroot of tree to the q
|
||||||
|
Q* search_path = new_Q();
|
||||||
|
QNode* n = new_qnode(tree.root);
|
||||||
|
q_add_node(search_path, n);
|
||||||
|
TreeNode* current_value;
|
||||||
|
int count_iterations = 1;
|
||||||
|
while (search_path->length > 0) {
|
||||||
|
count_iterations++;
|
||||||
|
current_value = q_remove_node(search_path);
|
||||||
|
|
||||||
|
if (current_value->value == value) {
|
||||||
|
free(search_path);
|
||||||
|
printf("total itarations: %d\n", count_iterations);
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_value->left != NULL) {
|
||||||
|
q_add_node(search_path, new_qnode(current_value->left));
|
||||||
|
}
|
||||||
|
if (current_value->right != NULL) {
|
||||||
|
q_add_node(search_path, new_qnode(current_value->right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("total itarations: %d\n", count_iterations);
|
||||||
|
free(search_path);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_leaf(TreeNode* a) {
|
||||||
|
if (a->left == NULL && a->right == NULL) {
|
||||||
|
return (true);
|
||||||
|
} else {
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine if two trees are equal
|
||||||
|
bool tree_equal(TreeNode* root_a, TreeNode* root_b) {
|
||||||
|
if (root_a->value != root_b->value) {
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_leaf(root_a) && is_leaf(root_b)) {
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_leaf(root_a) || is_leaf(root_b)) {
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tree_equal(root_a->left, root_b->left) && tree_equal(root_a->right, root_b->right));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The reason for choose the Q as the data strucuture to keep track
|
||||||
|
of the search path is to
|
||||||
|
*/
|
||||||
|
int main() {
|
||||||
|
TreeNode* root = new_tree_node(10);
|
||||||
|
TreeNode* root2 = new_tree_node(10);
|
||||||
|
Tree* tree = new_tree(root);
|
||||||
|
Tree* tree2 = new_tree(root2);
|
||||||
|
|
||||||
|
add_child_left(root, new_tree_node(5));
|
||||||
|
add_child_right(root, new_tree_node(7));
|
||||||
|
|
||||||
|
add_child_left(root->left, new_tree_node(12));
|
||||||
|
add_child_right(root->left, new_tree_node(8));
|
||||||
|
|
||||||
|
add_child_left(root->right, new_tree_node(88));
|
||||||
|
add_child_right(root->right, new_tree_node(14));
|
||||||
|
|
||||||
|
// create the second tree
|
||||||
|
add_child_left(root2, new_tree_node(5));
|
||||||
|
add_child_right(root2, new_tree_node(7));
|
||||||
|
|
||||||
|
add_child_left(root2->left, new_tree_node(12));
|
||||||
|
add_child_right(root2->left, new_tree_node(8));
|
||||||
|
|
||||||
|
add_child_left(root2->right, new_tree_node(88));
|
||||||
|
add_child_right(root2->right, new_tree_node(14));
|
||||||
|
|
||||||
|
bool answer;
|
||||||
|
answer = bf_search(*tree, 10);
|
||||||
|
printf("the answer is %s\n", answer ? "true" : "false");
|
||||||
|
|
||||||
|
bool trees_are_equal;
|
||||||
|
trees_are_equal = tree_equal(tree->root, tree2->root);
|
||||||
|
printf("are the trees equal? %s\n", trees_are_equal ? "yes" : "no");
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
Loading…
Reference in New Issue