GitLab system status is available here and here

Commit 73e1b493 authored by Jiaqi Duan's avatar Jiaqi Duan
Browse files

Add new file

parent 3824dfe5
/*
Name: Jiaqi Duan
CruzID: jduan10
Source file Name: List.c
IDE: XCode
*/
# include <stdio.h>
# include <stdlib.h>
# include "List.h"
/* ------------------------------ Structs ----------------------------------*/
// double linked list private NodeObj type
typedef struct NodeObj{
int data;
struct NodeObj* next;
struct NodeObj* prev;
} NodeObj;
// private Node type
typedef NodeObj* Node;
// private ListObj type
typedef struct ListObj{
Node front;
Node back;
Node curr; // current cursor node
int index; // store the location of cursor
int length;
} ListObj;
/* ----------------------- Constructors-Destructors ---------------------------*/
// Returns reference to new Node object. Initializes next and data fields.
Node newNode(int data){
Node N = malloc(sizeof(NodeObj));
N->data = data;
N->next = NULL;
N->prev = NULL;
return(N);
}
// Frees heap memory pointed to by *pN, sets *pN to NULL.
void freeNode(Node* pN){
if( pN!=NULL && *pN!=NULL ){
free(*pN);
*pN = NULL;
}
}
// Returns reference to new empty List object.
List newList(){
List L;
L = malloc(sizeof(ListObj));
L->front = L->back = L->curr = NULL;
L->length = 0;
L->index = -1;
return(L);
}
// Frees all heap memory associated with List *pL, and sets *pL to NULL.
void freeList(List* pL){
if(pL!=NULL && *pL!=NULL) {
clearList(*pL);
free(*pL);
*pL = NULL;
}
}
/* --------------------------- Access functions -------------------------------*/
// Returns the number of elements in L.
int length(List L){
if( L == NULL ){
printf("List Error: calling length() on NULL List reference\n");
exit(EXIT_FAILURE);
}
return(L->length);
}
// Returns index of cursor element if defined, -1 otherwise.
int indexElem(List L){
if(L == NULL){
printf("List Error: calling index() on NULL List reference\n");
exit(EXIT_FAILURE);
}
return(L->index);
}
// Returns front element of L. Pre: length()>0
int front(List L){
if(L == NULL){
printf("List Error: calling front() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0){
printf("List Error: calling front() on an empty List\n");
exit(EXIT_FAILURE);
}
return(L->front->data);
}
// Returns back element of L. Pre: length()>0
int back(List L){
if(L == NULL){
printf("List Error: calling back() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0){
printf("List Error: calling back() on an empty List\n");
exit(EXIT_FAILURE);
}
return(L->back->data);
}
// accessing an object that has already been deallocated.
// Returns cursor element of L. Pre: length()>0, index()>=0
int get(List L){
if(L == NULL){
printf("List Error: calling get() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0 || L->index < 0){
printf("List Error: calling get() on a List that is length()<=0, index()<0\n");
exit(EXIT_FAILURE);
}
return(L->curr->data);
}
// Returns true (1) iff Lists A and B are in same state, and returns false (0) otherwise.
int equals(List A, List B){
int eq = 0;
Node N = NULL;
Node M = NULL;
if( A==NULL || B==NULL ){
printf("List Error: calling equals() on NULL List reference\n");
exit(EXIT_FAILURE);
}
eq = ( A->length == B->length );
N = A->front;
M = B->front;
while(eq && N!=NULL){
eq = (N->data==M->data);
N = N->next;
M = M->next;
}
return(eq);
}
// Returns true (1) if Q is empty, otherwise returns false (0).
int isEmpty(List L){
int flag = 0; // set to False
if(L == NULL){
printf("List Error: calling isEmpty() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length == 0){
flag = 1;
}
return(flag);
}
/* ------------------------ Manipulation procedures ----------------------------*/
// Resets L to its original empty state.
void clearList(List L){
if(L == NULL){
printf("List Error: calling clear() on NULL List reference\n");
exit(EXIT_FAILURE);
}
// if there's only one element in the list
if(L->front == L->back){
freeNode(&L->front);
}else{
while(!isEmpty(L)){ // until the reaches to the end of the list
deleteFront(L);
}
}
L->back = L->front = L->curr = NULL;
L->length = 0;
L->index = -1;
}
// Overwrites the cursor element’s data with x. Pre: length()>0, index()>=0
void set(List L, int x){
if(L == NULL){
printf("List Error: calling set() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0 || L->index < 0){
printf("List Error: calling set() on a List that is length()<=0, index()<0\n");
exit(EXIT_FAILURE);
}
L->curr->data = x;
}
// If L is non-empty, sets cursor under the front element, otherwise does nothing.
void moveFront(List L){
if(L == NULL){
printf("List Error: calling moveFront() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(!isEmpty(L)){
L->curr = L->front;
L->index = 0;
}
}
// If L is non-empty, sets cursor under the back element, otherwise does nothing.
void moveBack(List L){
if(L == NULL){
printf("List Error: calling moveBack() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(!isEmpty(L)){
L->curr = L->back;
L->index = L->length - 1;
}
}
// If cursor is defined and not at front, move cursor one step toward the front of L;
// if cursor is defined and at front, cursor becomes undefined;
// if cursor is undefined do nothing
void movePrev(List L){
if(L == NULL){
printf("List Error: calling movePrev() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->index != -1 && L->curr != NULL && L->curr != L->front){
L->curr = L->curr->prev;
L->index--;
}else if(L->index != -1 && L->curr != NULL && L->curr == L->front){
L->curr = NULL;
L->index = -1;
}
}
// If cursor is defined and not at back, move cursor one step toward the back of L;
// if cursor is defined and at back, cursor becomes undefined;
// if cursor is undefined do nothing
void moveNext(List L){
if(L == NULL){
printf("List Error: calling moveNext() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->index != -1 && L->curr != NULL && L->curr != L->back){
L->curr = L->curr->next;
L->index++;
}else if(L->index != -1 && L->curr != NULL && L->curr == L->back){
L->curr = NULL;
L->index = -1;
}
}
// length change
// Insert new element into L. If L is non-empty, insertion takes place before front element.
void prepend(List L, int x){
Node N = newNode(x);
if(L == NULL){
printf("List Error: calling prepend() on NULL List reference\n");
exit(EXIT_FAILURE);
}
// if the list is empty then it will auto be the first and the back element in the list
if(isEmpty(L)){
L->front = L->back = N;
// set index to 0?
}else{
// set the next ptr of the new node to the front node
N->next = L->front;
// set the prev ptr of the new node NULL
N->prev = NULL;
// set the prev ptr of the front node to the new node
L->front->prev = N;
// update the new node as the front node
L->front = N;
}
if(L->index != -1){
L->index++;
}
L->length++;
}
// Insert new element into L. If L is non-empty, insertion takes place after back element.
void append(List L, int x){
Node N = newNode(x);
if(L == NULL){
printf("List Error: calling append() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(isEmpty(L)){
L->front = L->back = N;
// index = 0
}else{
// set next ptr of the new node NULL
N->next = NULL;
// set the prev ptr of the new node to the back node
N->prev = L->back;
// set the next ptr of the back node to the new node
L->back->next = N;
// update the new node as the back node
L->back = N;
}
L->length++;
}
// Insert new element before cursor. Pre: length()>0, index()>=0
void insertBefore(List L, int x){
Node N = newNode(x);
Node temp = NULL; // temp ptr as place holder
if(L == NULL){
printf("List Error: calling insertBefore() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0 || L->index < 0){
printf("List Error: calling insertBefore() on a List that is length()<=0, index()<0\n");
exit(EXIT_FAILURE);
}
// prepend?
// if there's only one node in the list
if(L->curr == L->front && L->curr == L->back){
N->prev = NULL;
L->front->prev = N;
N->next = L->front;
L->front = N; // update the front pointer
L->index = 1;
}else if(L->curr == L->front){ // if curr is pointing to the front
N->prev = NULL;
L->front->prev = N;
N->next = L->front;
L->front = N; // update the front pointer
}else{
// save the prev node of the cursor to temp
temp = L->curr->prev;
// set the prev ptr of the new node to temp
N->prev = temp;
// set the next ptr of the new node to the cursor
N->next = L->curr;
// set the prev ptr of cursor to the new node
L->curr->prev = N;
// set the next ptr of temp to the new node
temp->next = N;
}
if(L->index != -1){
L->index++;
}
// update length
L->length++;
}
// Insert new element after cursor. Pre: length()>0, index()>=0
void insertAfter(List L, int x){
Node N = newNode(x);
Node temp = NULL; // temp ptr as place holder
if(L == NULL){
printf("List Error: calling insertAfter() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0 || L->index < 0){
printf("List Error: calling insertAfter() on a List that is length()<=0, index()<0\n");
exit(EXIT_FAILURE);
}
// append?
// if there's only one node in the list
if(L->curr == L->front && L->curr == L->back){
L->curr->next = N;
N->next = NULL;
N->prev = L->curr;
L->back = N; // update the back pointer
}else if(L->curr == L->back){ // if curr is pointing to the back
N->next = NULL;
L->back->next = N;
N->prev = L->back;
L->back = N; // update the back pointer
}else{
// save the next node of the cursor to temp
temp = L->curr->next;
// set the next ptr of the new node to temp
N->next = temp;
// set the prev ptr of the new node to the cursor
N->prev = L->curr;
// set the next ptr of cursor to the new node
L->curr->next = N;
// set the prev ptr of temp to the new node
temp->prev = N;
}
// update length
L->length++;
}
// Delete the front element. Pre: length()>0
void deleteFront(List L){
Node temp = NULL; // temp ptr as place holder
if(L == NULL){
printf("List Error: calling deleteFront() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0){
printf("List Error: calling deleteFront() on a List that is length()<=0\n");
exit(EXIT_FAILURE);
}
// if cursor is pointing to front
if(L->curr == L->front){
L->curr = NULL; // disconnect the cursor with front
L->index = -1;
}
// if there's only one node in the list
if(L->front == L->back){
freeNode(&L->front);
L->front = L->back = NULL;
}else{
temp = L->front;
L->front = temp->next;
L->front->prev = NULL;
freeNode(&temp);
}
if(L->index != -1){
L->index--;
}
L->length--;
}
// Delete the back element. Pre: length()>0
void deleteBack(List L){
Node temp = NULL; // temp ptr as place holder
if(L == NULL){
printf("List Error: calling deleteBack() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0){
printf("List Error: calling deleteBack() on a List that is length()<=0\n");
exit(EXIT_FAILURE);
}
// freenode?
// if cursor is pointing to back
if(L->curr == L->back){
L->curr = NULL; // disconnect the cursor with back
L->index = -1;
}
// if there's only one node in the list
if(L->front == L->back){
freeNode(&L->back);
L->front = L->back = NULL;
}else{
temp = L->back;
L->back = temp->prev;
L->back->next = NULL;
freeNode(&temp);
}
L->length--;
}
// Delete cursor element, making cursor undefined. Pre: length()>0, index()>=0
void delete(List L){
if(L == NULL){
printf("List Error: calling delete() on NULL List reference\n");
exit(EXIT_FAILURE);
}
if(L->length <= 0 || L->index < 0){
printf("List Error: calling delete() on a List that is length()<=0, index()<0\n");
exit(EXIT_FAILURE);
}
// If there's only one node in the list
if(L->curr == L->front && L->curr == L->back){
freeNode(&L->curr);
L->front = L->back = NULL; // point front and back to NULL
}else if(L->curr == L->front){ // if at front, cut the connection from the list
L->curr->next->prev = L->curr->prev;
L->front = L->front->next; // move front forward
freeNode(&L->curr);
}else if(L->curr == L->back){ // if at back, cut the connection from the list
L->curr->prev->next = L->curr->next;
L->back = L->back->prev; // move back backwards
freeNode(&L->curr);
}else{
// set the next ptr of the node in front of cursor to the node behind cursor
L->curr->prev->next = L->curr->next;
// set the prev ptr of the node behind cursor to the node in front of cursor
L->curr->next->prev = L->curr->prev;
// set the next ptr and the prev ptr of cursor NULL
freeNode(&L->curr);
}
L->curr = NULL;
L->length--;
L->index = -1;
}
/* ----------------------------- Other operations -------------------------------*/
// Prints to the file pointed to by out, a string representation of L consisting
// of a space separated sequence of integers, with front on left.
void printList(FILE* out, List L){
Node N = NULL;
if(L == NULL){
printf("List Error: calling printList() on NULL List reference\n");
exit(EXIT_FAILURE);
}
for(N = L->front; N != NULL; N = N->next){
fprintf(out, "%d ", N->data);
}
fprintf(out, "\n");
}
// Returns a new List representing the same integer sequence as L. The cursor in
// the new list is undefined, regardless of the state of the cursor in L. The state
// of L is unchanged.
List copyList(List L){
Node N = NULL;
List newL = NULL; // new list for copy of L
if(L == NULL){
printf("List Error: calling copyList() on NULL List reference\n");
exit(EXIT_FAILURE);
}
newL = newList(); // reset to new list obj
for(N = L->front; N != NULL; N = N->next){
append(newL, N->data); // append a data into the new empty list
}
return(newL);
}
// connect A and B
// Returns a new List which is the concatenation of A and B. The cursor in the new List
// is undefined, regardless of the states of the cursors in A and B.
// The states of A and B are unchanged.
List concatList(List A, List B){
List AL = NULL; // A list copy
List BL = NULL; // B list copy
if(A == NULL || B == NULL){
printf("List Error: calling concatList() on NULL List reference\n");
exit(EXIT_FAILURE);
}
// copy list A to list AL and list B to list BL
AL = copyList(A);
BL = copyList(B);
// connect AL and BL
BL->front->prev = AL->back;
AL->back->next = BL->front;
// update the back ptr of BL to be the back ptr of AL
AL->back = BL->back;
// remove the back and front ptr of BL
BL->front = BL->back = BL->curr = NULL;
BL->index = -1;
// set the cursor in AL undefined
AL->curr = NULL;
AL->index = -1;
return(AL);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment