feat: last part of 2106 lab4

This commit is contained in:
Yadunand Prem 2023-11-06 18:08:30 +08:00
parent 9183d82953
commit fe0a63b2ba
No known key found for this signature in database
9 changed files with 789 additions and 0 deletions

View File

@ -0,0 +1,192 @@
#include "bintree.h"
#include "mymalloc.h"
#include <stdio.h>
#include <stdlib.h>
/* ------------------------- DO NOT IMPLEMENT THESE ----------------------
These are provided "free" to you, and you do not need to implement them,
though you MAY need to understand what they do. Some give you hints
on how to work with pointers to pointers. You MAY find some of these
functions useful.
------------------------------------------------------------------------- */
// Searches for the node containing "name" in the tree whose root is at "root",
// returning both the node ifself in "node", and its parent in "prevnode"
// (useful for deleting node). Both "node" and "prevnode" are set to NULL
// if name is not found in the tree.
void findNode(char *name, TTreeNode *root, TTreeNode **node,
TTreeNode **prevnode) {
TTreeNode *trav = root;
TTreeNode *prev = NULL;
while (trav != NULL) {
int cmp = strcmp(trav->name, name);
if (cmp == 0) {
*node = trav;
*prevnode = prev;
return;
}
prev = trav;
if (cmp < 0)
trav = trav->right;
else
trav = trav->left;
}
*node = NULL;
*prevnode = NULL;
}
// Searches for the node with the smallest value ("smallest node") in the tree
// originating at "node". Returns the smallest node and its parent in
// "smallest_node" and "parent" respectively.
void findSmallest(TTreeNode *node, TTreeNode **smallest_node,
TTreeNode **parent) {
TTreeNode *trav = node;
TTreeNode *prev = NULL;
if (trav == NULL)
return;
while (trav->left != NULL) {
prev = trav;
trav = trav->left;
}
*smallest_node = trav;
*parent = prev;
}
// Delete a node at "node" with parent node "prevnode"
void delNode(TTreeNode *node, TTreeNode *prevnode) {
// This is a leaf node
if (node->left == NULL && node->right == NULL) {
// See whether node is on parent's left or right, and NULL the
// corresponding pointer
int cmp = strcmp(prevnode->name, node->name);
// Previous node is smaller than this one. This
// node is on the right
if (cmp < 0)
prevnode->right = NULL;
else
prevnode->left = NULL;
freenode(node);
return;
}
// This has a child on the left only
if (node->right == NULL) {
// Copy the right child over
node = node->left;
freenode(node->left);
return;
}
// This has a child on the right only
if (node->left == NULL) {
node = node->right;
freenode(node->right);
return;
}
// This has children on both nodes
TTreeNode *smallest, *smallest_parent;
findSmallest(node->right, &smallest, &smallest_parent);
node = smallest;
smallest_parent->left = NULL;
freenode(smallest);
}
/* ---------------------------- IMPLEMENT THESE --------------------------- */
// Create a new node with name set to "name" and
// phoneNum set to "phoneNum".
void delTree(TTreeNode *root) {
// Implement deleting the entire tree, whose
// root is at "root".
if (root == NULL)
return;
if (root->left != NULL)
delTree(root->left);
if (root->right != NULL)
delTree(root->right);
freenode(root);
}
TTreeNode *makeNewNode(char *name, char *phoneNum) {
TTreeNode *node = mymalloc(sizeof(TTreeNode));
node->name = mymalloc(strlen(name) + 1);
strcpy(node->name, name);
strcpy(node->phoneNum, phoneNum);
node->left = NULL;
node->right = NULL;
return node;
// Implement makeNewNode to create a new
// TTreeNode containing name and phoneNum
}
// Add a new node to the tree.
// Note that "root" is a POINTER to the tree's root,
// not the root itself.
void addNode(TTreeNode **root, TTreeNode *node) {
if (*root == NULL) {
*root = node;
}
TTreeNode **trav = root;
while (1) {
int cmp = strcmp((*trav)->name, node->name);
if (cmp == 0)
return;
if (cmp > 0) {
if ((*trav)->left == NULL)
(*trav)->left = node;
else {
trav = &((*trav)->left);
continue;
}
} else if (cmp < 0) {
if ((*trav)->right == NULL)
(*trav)->right = node;
else {
trav = &((*trav)->right);
continue;
}
}
}
// Add a new node to the tree, where root is
// the POINTER to the tree's root.
}
void freenode(TTreeNode *node) {
myfree(node->name);
myfree(node);
// Frees the memory used by node.
}
void print_inorder(TTreeNode *node) {
// Implement in-order printing of the tree
// Recursion is probably best here.
if (node == NULL)
return;
if (node->left != NULL)
print_inorder(node->left);
printf("Name is %s Number is %s\n", node->name, node->phoneNum);
if (node->right != NULL)
print_inorder(node->right);
}

View File

@ -0,0 +1,17 @@
#include <string.h>
#include <stdlib.h>
typedef struct tn {
char *name;
char phoneNum[9];
struct tn *left, *right;
} TTreeNode;
void findNode(char *, TTreeNode *, TTreeNode **, TTreeNode **);
void findSmallest(TTreeNode *, TTreeNode **, TTreeNode **);
void delNode(TTreeNode *, TTreeNode *);
void delTree(TTreeNode *);
TTreeNode *makeNewNode(char *, char *);
void addNode(TTreeNode **, TTreeNode *);
void freenode(TTreeNode *);
void print_inorder(TTreeNode *);

View File

@ -0,0 +1,239 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "llist.h"
//#define DEBUG // Enable debug printing
// Debug printer
void dbprintf(char *format, ...) {
#ifdef DEBUG
va_list args;
va_start(args, format);
vprintf(format, args);
#endif
}
// Implements a double linked list.
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data) {
TNode *node = malloc(sizeof(TNode));
node->key = key;
node->pdata = data;
node->prev = NULL;
node->next = NULL;
return node;
}
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir) {
if(*llist == NULL) {
*llist = node;
(*llist)->trav = *llist;
(*llist)->tail = *llist;
}
else
if(((*llist)->key >= node->key && dir == 0) || (((*llist)->key <= node->key) && dir == 1)) {
node->next = *llist;
(*llist)->prev = node;
*llist = node;
(*llist)->trav = *llist;
}
else
{
TNode *trav = *llist;
if(dir == 0)
while(trav->next != NULL && trav->key < node->key)
trav = trav->next;
else if(dir == 1)
while(trav->next != NULL && trav->key > node->key)
trav = trav->next;
if(trav->next == NULL && ((trav->key < node->key && dir == 0) ||
(trav->key > node->key && dir == 1))) {
trav->next = node;
node->prev = trav;
// Set the tail
(*llist)->tail = node;
} else {
// Insert into the previous space
node->next = trav;
if(trav->prev != NULL) {
trav->prev->next = node;
node->prev = trav->prev;
}
if(trav->next != NULL) {
}
trav->prev = node;
}
}
}
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node) {
if(*llist == NULL || node == NULL)
return;
if((*llist)->key == node->key) {
// Node to be deleted is at the front of the list.
*llist = (*llist)->next;
// Ensure that we don't point to it anymore.
if(*llist != NULL)
(*llist)->prev = NULL;
}
else
{
TNode *trav = *llist;
while(trav != NULL && trav->key != node->key)
trav = trav->next;
// We've found the deletion point
if(trav != NULL) {
trav->prev->next = trav->next;
if(trav->next != NULL)
trav->next->prev = trav->prev;
else
(*llist)->tail = trav->prev;
}
}
free(node);
}
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key) {
if(llist == NULL)
return NULL;
TNode *trav = llist;
while(trav != NULL && trav->key != key)
trav = trav->next;
return trav;
}
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir) {
if(dir == 0) {
if(node->prev == NULL)
return;
delete_node(&llist, node);
}
else
if(dir == 1) {
if(node->next == NULL)
return;
delete_node(&llist, node->next);
}
}
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *)) {
TNode *trav = llist;
while(trav) {
func(trav);
trav = trav->next;
}
}
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist) {
TNode *trav = *llist, *tmp;
while(trav) {
tmp = trav->next;
free(trav);
trav = tmp;
}
*llist = NULL;
}
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where)
{
if(llist == NULL)
return;
if(where == FRONT)
llist->trav = llist;
else
if(where == REAR)
llist->trav = llist->tail;
}
// Get the next node
TNode *succ(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->next;
return ret;
}
// Get the previous node
TNode *pred(TNode *llist)
{
if(llist == NULL)
return NULL;
TNode *ret = llist->trav;
if(llist->trav != NULL)
llist->trav = llist->trav->prev;
return ret;
}

View File

@ -0,0 +1,115 @@
#include <stdbool.h>
#include <stdio.h>
// Uncomment the next line to enable debug printing
#define DEBUG // Enable debug printing
// The debug printer; used like a normal printf, except
// that printing can be turned off by commenting out the
// #define DEBUG above.
void dbprintf(char *format, ...);
// You should modify this structure to hold
// whatever you need to implement your
// memory manager. You can delete the
// val field. It is only used for testlist.c
typedef struct td {
bool occupied;
size_t size;
} TData;
/* -----------------------------------------
BASIC ROUTINES
Basic linked list routines
---------------------------------------- */
// Basic double linked list node.
typedef struct tn {
unsigned int key;
TData *pdata; // Pointer to the data you want to store
struct tn *trav; // Only used in the root for traversal
struct tn *tail; // Only used in the root for finding the end of the list
struct tn *prev;
struct tn *next;
} TNode;
// Insert Direction
#define ASCENDING 0
#define DESCENDING 1
// Merge direction
#define PRECEDING 0
#define SUCCEEDING 1
// Traverser position
#define FRONT 0
#define REAR 1
// Create a new node. You need to
// Create your own TData node, populate
// it, then create a new node with a suitable
// key. Insertion into the link list is
// by ascending order of the key. An example key
// might be the starting address of a memory segment.
TNode *make_node(unsigned int key, TData *data);
// Inserts a node into the correct point of the
// double linked list. The list is sorted
// in ascending order of the key. Duplicate keys
// are permitted, though not recommended.
// llist = Pointer to link list
// node = Pointer to node created by make_node
// dir = 0: Insert in ascending order
// dir = 1: Insert in descending order
void insert_node(TNode **llist, TNode *node, int dir);
// Remove a given node from the linked list
void delete_node(TNode **llist, TNode *node);
// Find a node that has the value of key
// If there are duplicate keys, the first one encountered
// will be returned.
TNode *find_node(TNode *llist, unsigned int key);
// Merge the node provided with either the node after or the node before.
// You need to manage merging the data in node->pdata yourself. This code just
// deletes the larger of the two nodes.
// dir = 0: Merge with node before
// dir = 1: Merge with node after
void merge_node(TNode *llist, TNode *node, int dir);
// Purge the entire list. You must
// free any dynamic data in the TData
// struct yourself.
void purge_list(TNode **llist);
/* -----------------------------------------
TRAVERSAL ROUTINES
Lets you traverse the linked list
---------------------------------------- */
// Go over every element of llist, and call func
// func prototype is void func(TNode *);
void process_list(TNode *llist, void (*func)(TNode *));
// Reset traverser
// where=0 START: Resets traverser to start of list
// where=1 END: Rsets
void reset_traverser(TNode *llist, int where);
// Get the next node
TNode *succ(TNode *llist);
// Get the previous node
TNode *pred(TNode *llist);

View File

@ -0,0 +1,103 @@
#include "mymalloc.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/_types/_null.h>
#include "llist.h"
char _heap[MEMSIZE] = {0};
TNode *_memlist = NULL; // To maintain information about length
// Do not change this. Used by the test harness.
// You may however use this function in your code if necessary.
long get_index(void *ptr) {
if (ptr == NULL)
return -1;
else
return (long)((char *)ptr - &_heap[0]);
}
// Allocates size bytes of memory and returns a pointer
// to the first byte.
void *mymalloc(size_t size) {
if (_memlist == NULL) {
TData *data = malloc(sizeof(TData));
data->occupied = false;
data->size = MEMSIZE;
_memlist = make_node(0, data);
}
// loop through the list to find a free block
// if found, split the block and return the pointer
// if not found, return NULL
TNode *curr = _memlist;
TNode *best = NULL;
while (curr != NULL) {
if (curr->pdata->occupied == true) {
curr = curr->next;
continue;
}
if (curr->pdata->size < size) {
curr = curr->next;
continue;
}
if (best == NULL) {
best = curr;
curr = curr->next;
continue;
}
if (best->pdata->size > curr->pdata->size) {
best = curr;
curr = curr->next;
continue;
}
curr = curr->next;
}
if (best == NULL)
return NULL;
best->pdata->occupied = true;
if (best->pdata->size > size) {
// Create a new node with the leftover space
TData *newData = malloc(sizeof(TData));
newData->occupied = false;
newData->size = best->pdata->size - size;
TNode *newNode = make_node(best->key + size, newData);
// insert new node after the current one in the list.
insert_node(&_memlist, newNode, 0);
// change the size of the current node.
best->pdata->size = size;
}
return &_heap[best->key];
}
// Frees memory pointer to by ptr.
void myfree(void *ptr) {
if (ptr == NULL)
return;
long index = get_index(ptr);
TNode *node = find_node(_memlist, index);
if (node == NULL)
return;
node->pdata->occupied = false;
// merge with the next node if it is free
while (node->next != NULL && node->next->pdata->occupied == false) {
node->pdata->size += node->next->pdata->size;
merge_node(_memlist, node, 1);
}
while (node->prev != NULL && node->prev->pdata->occupied == false) {
TNode *prev = node->prev;
prev->pdata->size += node->pdata->size;
merge_node(_memlist, node, 0);
}
}
void print_node(TNode *node) {
printf("Status: %s Start index: %d Length: %zu\n",
node->pdata->occupied ? "ALLOCATED" : "FREE", node->key,
node->pdata->size);
}
void print_memlist() { process_list(_memlist, print_node); }

View File

@ -0,0 +1,7 @@
#include <stdio.h>
#define MEMSIZE 64 * 1024 // Size of memory in bytes
long get_index(void *ptr);
void print_memlist();
void *mymalloc(size_t);
void myfree(void *);

View File

@ -0,0 +1,51 @@
#include <stdio.h>
#include "phonebook.h"
#include "bintree.h"
static TTreeNode *_root = NULL;
char *findPerson(char *name)
{
TTreeNode *node, *prev;
findNode(name, _root, &node, &prev);
if (node != NULL)
return node->phoneNum;
else
return NULL;
}
void print_phonebook()
{
print_inorder(_root);
}
void addPerson(char *name, char *phoneNum)
{
if (findPerson(name) == NULL)
{
TTreeNode *node = makeNewNode(name, phoneNum);
addNode(&_root, node);
}
else
printf("%s is already in phonebook.\n", name);
}
void delPerson(char *name)
{
TTreeNode *node, *prevnode;
findNode(name, _root, &node, &prevnode);
if (node == NULL)
{
printf("Unable to find %s\n", name);
return;
}
delNode(node, prevnode);
}
void delPhonebook()
{
delTree(_root);
_root = NULL;
}

View File

@ -0,0 +1,5 @@
char *findPerson(char *);
void addPerson(char *, char *);
void delPerson(char *);
void print_phonebook();
void delPhonebook();

View File

@ -0,0 +1,60 @@
#include <stdio.h>
#include "phonebook.h"
#define ITEMS 5
typedef struct d
{
char *name, *tel;
} TData;
void printResult(char *name)
{
char *result;
printf("Looking for %s ", name);
result = findPerson(name);
if (result == NULL)
printf("NOT FOUND\n");
else
printf(" Number is %s\n", result);
}
int main()
{
TData data[ITEMS] = {{"Fred Astaire", "95551234"}, {"Jean Valjean", "95558764"}, {"Gal Gadot", "95551123"}, {"Aiken Dueet", "95558876"}, {"Victor Hugo", "95524601"}};
int i;
for (i = 0; i < ITEMS; i++)
{
printf("Adding %s, phone number %s\n", data[i].name, data[i].tel);
addPerson(data[i].name, data[i].tel);
}
printf("\nNow retrieiving stored data.\n");
char *result;
for (i = 0; i < ITEMS; i++)
{
printResult(data[i].name);
}
printf("\nRetrieving unknown person.\n");
printResult("Wee Tu Loh");
printf("\nPrinting entire phonebook.\n");
print_phonebook();
printf("\nDeleting Aiken Dueet.\n");
delPerson("Aiken Dueet");
print_phonebook();
printf("\nDeleting Victor Hugo.\n");
delPerson("Victor Hugo");
print_phonebook();
printf("\nDeleting entire phone book.\n");
delPhonebook();
print_phonebook();
}