diff --git a/assignment1/problem1/Makefile b/assignment1/problem1/Makefile new file mode 100644 index 0000000..779f6f5 --- /dev/null +++ b/assignment1/problem1/Makefile @@ -0,0 +1,5 @@ +EXEC = list +SRC = $(wildcard *.c) + +$(EXEC): $(SRC) + gcc -o $@ $^ -Wall diff --git a/assignment1/problem1/list.c b/assignment1/problem1/list.c new file mode 100644 index 0000000..36ec53e --- /dev/null +++ b/assignment1/problem1/list.c @@ -0,0 +1,195 @@ +/* + * Author: Walter + * Student ID: 1930006025 + * Assignment_1_problem_1 + */ + +#include "list.h" +#include +#include +#include + +// Write all your functions here. +bool IsEmpty(Node *head) { + if (head == NULL) { + return true; + } else { + return false; + } +} + +/* code from pdf */ +Node *InsertNode(Node **phead, int index, double x) { + if (index < 0) + return NULL; + int currIndex = 1; + Node *currNode = *phead; + while (currNode != NULL && index > currIndex) { + currNode = currNode->next; + currIndex++; + } + if (index > 0 && currNode == NULL) + return NULL; + Node *newNode = (Node *)malloc(sizeof(Node)); + newNode->data = x; + if (index == 0) { + newNode->next = *phead; + *phead = newNode; + } else { + newNode->next = currNode->next; + currNode->next = newNode; + } + return newNode; +} + +int FindNode(Node *head, double x) { + int position; + Node *pnode; + + /* position start from 1 */ + for (pnode = head, position = 1; pnode; pnode = pnode->next, position++) { + if (pnode->data == x) { + return position; + } + } + + return 0; +} + +int DeleteNode(Node **phead, double x) { + /* position start from 1 */ + int position; + Node *pnode; + Node *delNode; + + /* if delete the first node */ + if ((*phead)->data == x) { + delNode = *phead; + *phead = (*phead)->next; + free(delNode); + return 1; + } + + /* if not the first node */ + for (pnode = *phead, position = 2; pnode->next; + pnode = pnode->next, position++) { + /* loop for pnode->next->data == x */ + if (pnode->next->data == x) { + /* delete node */ + delNode = pnode->next; + pnode->next = pnode->next->next; + free(delNode); + return position; + } + } + + /* if node not found, return 0 */ + return 0; +} + +void DisplayList(Node *head) { + Node *pnode; + /* loop for each node */ + for (pnode = head; pnode; pnode = pnode->next) { + printf("%f ", pnode->data); + } + /* new line at the end */ + printf("\n"); +} + +void DestroyList(Node *head) { + Node *pnode = head; + Node *delNode; + /* loop for each node */ + while (pnode) { + /* store the tmp node */ + delNode = pnode; + pnode = pnode->next; + free(delNode); + } +} + +void InverstNode(Node **head) { + /* empty list */ + if (*head == NULL) { + return; + } + + /* only one node in list */ + if ((*head)->next == NULL) { + return; + } + + /* reverse Node */ + Node *a, *b, *c; + a = NULL; + b = *head; + c = (*head)->next; + + /* when c == NULL, b is the end of linked list */ + while (c) { + /* reverse node */ + b->next = a; + /* move a, b, c forward */ + a = b; + b = c; + c = c->next; + } + /* finanl step */ + b->next = a; + /* reset head */ + *head = b; +} + +void RemoveDuplicates(Node **head) { + Node *newHead = NULL, *currNode = *head; + double oldValue; + int position; + + /* empty list, no need to do anything */ + if ((*head) == NULL) { + return; + } + + /* only one node in the list, no need to do anything */ + if ((*head)->next == NULL) { + return; + } + + /* loop until currNode point at NULL */ + while (currNode) { + /* check whether there is any same value node after this node */ + position = FindNode(currNode->next, currNode->data); + + /* position is not 0, means this is the duplicated value */ + if (position) { + /* record current duplicated value */ + oldValue = currNode->data; + + /* then use a for loop jump pass the duplicated value, + * use for loop to check currNode is not NULL + * before get currNode->data */ + for (; currNode; currNode=currNode->next) { + /* exit when we find a new value */ + if (currNode->data != oldValue) { + break; + } + } + + continue; + } + + /* if this is not a duplicated value, + * add unique node to new linked list */ + InsertNode(&newHead, 0, currNode->data); + + /* move to next */ + currNode = currNode->next; + } + + /* Inverst to original direction */ + InverstNode(&newHead); + /* reset head, remember to destory old list, avoid memory leak */ + DestroyList(*head); + *head = newHead; +} diff --git a/assignment1/problem1/list.h b/assignment1/problem1/list.h new file mode 100644 index 0000000..43c053a --- /dev/null +++ b/assignment1/problem1/list.h @@ -0,0 +1,58 @@ +#ifndef MY_STACK +#define MY_STACK + +#include + +typedef struct node { + double data; + struct node *next; +} Node; + +/* function: tests whether a list is empty +input: head: pointer to the first node +output: true if the list is empty and false otherwise +*/ +bool IsEmpty(Node *head); + +/* function: inserts a new node with certain data after a certain position +input: phead: pointer to the pointer to the first node +index: the new node is inserted after position index +insert a new node as the head if index is 0 +x: data of the new node +output: a pointer to the new node if insertion is successful, NULL otherwise +*/ +Node *InsertNode(Node **phead, int index, double x); + +/* function: finds node with certain data +input: head: pointer to the first node +x: the first node whose data = x is returned +output: returns the position of the first node whose data = x +returns 0 if no such node exists +*/ +int FindNode(Node *head, double x); + +/* function: deletes a node with certain data +input: phead: pointer to the pointer to the first node +x: the first node whose data = x is deleted +output: returns the position of the deleted node +returns 0 if no such node exists +*/ +int DeleteNode(Node **phead, double x); + +/* function: prints all the nodes in the list +input: head: pointer to the first node +*/ +void DisplayList(Node *head); + +/* function: deletes all the nodes in the list and frees their memory +input: head: pointer to the first node +*/ +void DestroyList(Node *head); + +/* inverse a linked list */ +void InverstNode(Node **head); + +/* delete all duplicates node in a linked list */ +void RemoveDuplicates(Node **head); + +#endif diff --git a/assignment1/problem1/test_main.c b/assignment1/problem1/test_main.c new file mode 100644 index 0000000..dc2738b --- /dev/null +++ b/assignment1/problem1/test_main.c @@ -0,0 +1,180 @@ +/* author: Walter + * Student_ID: 1930006025 + * Assignment_problem_1 + * This is a test unit file contain some test function and a main function to run it + */ + +#include +#include + +#include "list.h" + +void test_inverse_empty_list(); +void test_inverse_one_list(); +void test_inverst_list(); +void test_remove_duplicate(); + +int main() { + test_inverse_empty_list(); + test_inverse_one_list(); + test_inverst_list(); + test_remove_duplicate(); +} + +void test_inverse_empty_list() { + Node *head = NULL; + printf("test_inverse_empty_list(): except 2 empty line:\n"); + DisplayList(head); + InverstNode(&head); + DisplayList(head); +} + +void test_inverse_one_list() { + Node *head = NULL; + printf("test_inverse_one_list(): except two same node:\n"); + InsertNode(&head, 0, 39.0); + DisplayList(head); + InverstNode(&head); + DisplayList(head); + DestroyList(head); + head = NULL; +} + +void test_inverst_list() { + Node *head = NULL; + printf("test_inverst_list(): except inverse list:\n"); + for (int i=39; i<45; i++) { + InsertNode(&head, 0, (double)i); + } + DisplayList(head); + InverstNode(&head); + DisplayList(head); + DestroyList(head); + head = NULL; +} + +/* four test cases from pdf */ +void test_remove_duplicate() { + Node *head = NULL; + + printf("test_remove_duplicate(): except 1.0 4.0:\n"); + InsertNode(&head, 0, 1.0); + InsertNode(&head, 1, 2.0); + InsertNode(&head, 2, 2.0); + InsertNode(&head, 3, 4.0); + InsertNode(&head, 4, 6.0); + InsertNode(&head, 5, 6.0); + DisplayList(head); + RemoveDuplicates(&head); + DisplayList(head); + DestroyList(head); + head = NULL; + + printf("test_remove_duplicate(): except two empty line:\n"); + head = NULL; + DisplayList(head); + RemoveDuplicates(&head); + DisplayList(head); + DestroyList(head); + head = NULL; + + printf("test_remove_duplicate(): except empty line in result:\n"); + head = NULL; + InsertNode(&head, 0, 6.0); + InsertNode(&head, 1, 6.0); + InsertNode(&head, 2, 6.0); + InsertNode(&head, 3, 7.0); + InsertNode(&head, 4, 7.0); + DisplayList(head); + RemoveDuplicates(&head); + DisplayList(head); + DestroyList(head); + head = NULL; + + printf("test_remove_duplicate(): except 6.0 7.0:\n"); + head = NULL; + InsertNode(&head, 0, 6.0); + InsertNode(&head, 1, 7.0); + DisplayList(head); + RemoveDuplicates(&head); + DisplayList(head); + DestroyList(head); + head = NULL; + return; +} + + +/* old test function +// Testing all the functions: +int main(void) { + Node *head = NULL; + + // Output: true + printf("%s\n", IsEmpty(head) ? "true" : "false"); + + // Must output an empty line: + DisplayList(head); + + // Must output "insert failed": + Node *result = InsertNode(&head, 20, 7); + printf("%s\n", result == NULL ? "insert failed" : "insert succeeded"); + + // Output: 0.000000 1.000000 2.000000 3.000000 4.000000 + for (int i = 0; i < 5; i++) { + InsertNode(&head, i, i); + } + DisplayList(head); + + // Output: false + printf("%s\n", IsEmpty(head) ? "true" : "false"); + + // Output: 4.000000 3.000000 2.000000 1.000000 0.000000 + // 0.000000 1.000000 2.000000 3.000000 4.000000 + for (int i = 0; i < 5; i++) { + InsertNode(&head, 0, i); + } + DisplayList(head); + + // Output: 0.000000 is at position 5 + // 2.000000 is at position 3 + // 4.000000 is at position 1 + // 6.000000 is not in the list + for (int i = 0; i < 7; i += 2) { + int idx = FindNode(head, i); + if (idx > 0) { + printf("%f is at position %d\n", (double)i, idx); + } else { + printf("%f is not in the list\n", (double)i); + } + } + + // Output: inserted 10.000000 + // 4.000000 3.000000 2.000000 10.000000 1.000000 0.000000 + // 0.000000 1.000000 2.000000 3.000000 4.000000 + Node *in = InsertNode(&head, 3, 10); + printf("inserted %f\n", in->data); + DisplayList(head); + + // Output: 4.000000 3.000000 2.000000 10.000000 1.000000 + // 0.000000 1.000000 2.000000 3.000000 4.000000 + // 3.000000 2.000000 10.000000 1.000000 + // 0.000000 1.000000 2.000000 3.000000 4.000000 + // 3.000000 2.000000 10.000000 1.000000 + // 0.000000 1.000000 2.000000 3.000000 + DeleteNode(&head, 0); // Delete in the middle of the list. + DisplayList(head); + DeleteNode(&head, 4); // Delete at the front of the list. + DisplayList(head); + DeleteNode(&head, 4); // Delete at the end of the list. + DisplayList(head); + + printf("Reverse List ...\n"); + InverstNode(&head); + DisplayList(head); + + DestroyList(head); + head = NULL; + + return 0; +} +*/