fixed deleteForward and deleteBackward

doubly_linked_list.cpp

Committer:
conantina
Date:
2016-10-12
Revision:
0:294bc2018c3a
Child:
1:c24e4dd27d48

File content as of revision 0:294bc2018c3a:

#include <stdlib.h>
#include <stdio.h>
#include "doubly_linked_list.h"


/**
 * create_llnode
 *
 * Helper function that creates a node by allocating memory for it on the heap,
 * and initializing any pointers in it to NULL.
 *
 * @param data A void pointer to data the user is adding to the doublely linked list.
 * @return The llnode
 */
LLNode* create_llnode(void* data) {
    LLNode* newNode = (LLNode*)malloc(sizeof(LLNode));
    newNode->data = data;
    newNode->previous = NULL;
    newNode->next = NULL;
    return newNode;
}


/**
 * create_dlinkedlist
 *
 * Creates a doublely liked list by allocating memory for it on the heap. Initialize the size to zero, as well as head and tail to NULL.
 *
 * @return An empty dlinkedlist
 */
DLinkedList* create_dlinkedlist(void) {
    DLinkedList* newList = (DLinkedList*)malloc(sizeof(DLinkedList));
    newList->head = NULL;
    newList->tail = NULL;
    newList->current = NULL;
    newList->size = 0;
    return newList;
}

/**
 * insertHead
 *
 * insert the data to the head of the doublely linked list
 *
 * @param data A void pointer to data the user is adding to the doublely linked list.
 * 
 */

void insertHead(DLinkedList* dLinkedList, void* data){
  LLNode* newNode = create_llnode(data);
  if(dLinkedList->head == NULL){
    dLinkedList->size++;
    dLinkedList->head = newNode;
    dLinkedList->current = newNode;
    dLinkedList->tail = newNode;
  }else{
    dLinkedList->size++;
    newNode->next = dLinkedList->head;
    (dLinkedList->head)->previous = newNode;
    dLinkedList->head = newNode;
  }
}

/**
 * insertEnd
 *
 * insert the data to the tail of the doublely linked list
 *
 * @param data A void pointer to data the user is adding to the doublely linked list.
 * 
 */

void insertTail(DLinkedList* dLinkedList, void* data){
  LLNode* newNode = create_llnode(data);
  if(dLinkedList->tail == NULL){
    dLinkedList->size++;
    dLinkedList->head = newNode;
    dLinkedList->current = newNode;
    dLinkedList->tail = newNode;
  }else{
    dLinkedList->size++;
    newNode->previous = dLinkedList->tail;
    (dLinkedList->tail)->next = newNode;
    dLinkedList->tail = newNode;
  }
}

/**
 * insertAfter
 *
 * insert the new data to the doublely linked list right after the current pointer
 *
 * @param newData A void pointer to the new data that the user want to add after data
 * @return 1 if insert the new data successfully
 *         0 if not
 */

int insertAfter(DLinkedList* dLinkedList, void* newData){
  if(dLinkedList->current == NULL){
    return 0;
  }else{
    LLNode* newNode = create_llnode(newData);
    newNode->previous =  dLinkedList->current;
    newNode->next =  (dLinkedList->current)->next;
    if(dLinkedList->current == dLinkedList->tail){
      dLinkedList->tail = newNode;
    }else{
      ((dLinkedList->current)->next)->previous = newNode;    
    }
    (dLinkedList->current)->next = newNode;
    dLinkedList->size++;
    return 1;     
  }

}
/**
 * insertBefore
 *
 * insert the new data to the doublely linked list right before the current pointer
 *
 * @param newData A void pointer to the new data that the user want to add after data
 * @return 1 if insert the new data successfully
 *         0 if not
 */

int insertBefore(DLinkedList* dLinkedList, void* newData){
  if(dLinkedList->current == NULL){
    return 0;
  }else{
    LLNode* newNode = create_llnode(newData);
    newNode->next = dLinkedList->current;
    newNode->previous = (dLinkedList->current)->previous;
    if(dLinkedList->current == dLinkedList->head){
      dLinkedList->head = newNode;
    }else{
      ((dLinkedList->current)->previous)->next = newNode;
    }
    (dLinkedList->current)->previous = newNode;
    dLinkedList->size++;
    return 1;
  }
}

/**
 * deleteBackward
 *
 * delete the node the current pointer is pointed at, and move the pointer backwards
 *
 * @param  free_func The function that the user created to free the data.
 * @return 1 if deleted successfully
 *         0 if not
 */

void* deleteBackward(DLinkedList* dLinkedList, dll_op free_func){
  if(dLinkedList->current != NULL){
    LLNode* deleteNode = dLinkedList->current;
    if((dLinkedList->current)->next != NULL){
      ((dLinkedList->current)->next)->previous = (dLinkedList->current)->previous;   
    }
    if((dLinkedList->current)->previous != NULL){
      ((dLinkedList->current)->previous)->next = (dLinkedList->current)->next;
    }
    if((dLinkedList->current) == (dLinkedList->tail)){
      dLinkedList->tail = (dLinkedList->current)->previous;
    }
    if((dLinkedList->current) == (dLinkedList->head)){
      dLinkedList->head = (dLinkedList->current)->next;
    }
    if((dLinkedList->current)->previous != NULL){
      dLinkedList->current = (dLinkedList->current)->previous;
    }else{
      dLinkedList->current = NULL;
    }
    free_func(deleteNode->data);
    free(deleteNode);
    dLinkedList->size--;
    if(dLinkedList->current != NULL){
      return (dLinkedList->current)->data;
    }else{
      return NULL;
    }
  }else{
    return NULL;
  }
}


/**
 * deleteForward
 *
 * delete the node the current pointer is pointed at, and move the pointer to the next
 *
 * @param  free_func The function that the user created to free the data.
 * @return 1 if deleted successfully
 *         0 if not
 */

void* deleteForward(DLinkedList* dLinkedList, dll_op free_func){
  if(dLinkedList->current != NULL){
    LLNode* deleteNode = dLinkedList->current;
    if((dLinkedList->current)->next != NULL){
      ((dLinkedList->current)->next)->previous = (dLinkedList->current)->previous;
    }
    if((dLinkedList->current)->previous != NULL){
      ((dLinkedList->current)->previous)->next = (dLinkedList->current)->next;
    }
    if((dLinkedList->current) == (dLinkedList->tail)){
      dLinkedList->tail = (dLinkedList->current)->previous;
    }
    if((dLinkedList->current) == (dLinkedList->head)){
      dLinkedList->head = (dLinkedList->current)->next;
    }
    if((dLinkedList->current)->next != NULL){
      dLinkedList->current = (dLinkedList->current)->next;
    }else{
      dLinkedList->current = NULL;
    }
    free_func(deleteNode->data);
    free(deleteNode);
    dLinkedList->size--;
    if(dLinkedList->current != NULL){
      return (dLinkedList->current)->data;
    }else{
      return NULL;
    }
  }else{
    return NULL;
  }
}


/**
 * traverseList
 *
 * traverse the list and do something on each pieae of data
 *
 * @param  do_func The function to perform on each piece of data.
 *
 */

void traverseList(DLinkedList* dLinkedList, dll_op do_func){
  if(dLinkedList->head != NULL){
    LLNode* thisNode = dLinkedList->head;
    do{
      do_func(thisNode->data);
      thisNode = thisNode->next;
    }while(thisNode != NULL);
  }else{
    if(dLinkedList->head == NULL){
        printf("Null head\n");
    }
     if(dLinkedList->tail == NULL){
        printf("Null tail\n");
    }
      if(dLinkedList->current == NULL){
        printf("Null current\n");
    }
  }
}


/**
 * destroyList
 *
 * Destroy the doublely linked list. Everything in the linked list including list structure,
 * nodes and data are all freed from the heap.
 *
 * @param  do_func The function to perform on each piece of data.
 *
 */

void destroyList(DLinkedList* dLinkedList, dll_op free_func){
  if(dLinkedList->head != NULL){
    getHead(dLinkedList);
    while(deleteForward(dLinkedList,free_func)){};
  }
  free(dLinkedList);
}


/**
 * getHead
 *
 * return the data contained in the head of the doublely linked list, and set the current pointer
 * to head
 * @return the head data or  NULL if head == NULL
 */

void* getHead(DLinkedList* dLinkedList){
  if(dLinkedList->head != NULL){
    dLinkedList->current = dLinkedList->head;
    return (dLinkedList->head)->data;
  }else{
    return NULL;
  }
}

/**
 * getTail
 *
 * return the data contained in the tail of the doublely linked list, and set the current pointer
 * to tail
 * @return the tail data or  NULL if tail == NULL
 */
void* getTail(DLinkedList* dLinkedList){
  if(dLinkedList->tail != NULL){
    dLinkedList->current = dLinkedList->tail;
    return (dLinkedList->tail)->data;
  }else{
    return NULL;
  }
}

/**
 * getTail
 *
 * return the data the current pointer is pointing at
 * @return the current data or  NULL if current == NULL
 */

void* getCurrent(DLinkedList* dLinkedList){
  if((dLinkedList->current) == NULL){
    return NULL;
  }else {
    return (dLinkedList->current)->data;
  }
}

/**
 * getNext
 *
 * return the next data the current pointer is pointing at, and move the current pointer to next
 * @return the next data or  NULL if current == NULL
 */

void* getNext(DLinkedList* dLinkedList){
  if(dLinkedList->current == NULL){
    return NULL;
  }else if((dLinkedList->current)->next == NULL){
    dLinkedList->current = NULL;
    return NULL;
  }else {
    dLinkedList->current = dLinkedList->current->next;
    return dLinkedList->current->data;
  }
}

/**
 * getPrevious
 *
 * return the previous data the current pointer is pointing at, and move the current pointer to 
 * previous
 * @return the previous data or  NULL if current == NULL
 */

void* getPrevious(DLinkedList* dLinkedList){
  if(dLinkedList->current == NULL){
    return NULL;
  }else if((dLinkedList->current)->previous == NULL){
    dLinkedList->current = NULL;
    return NULL;
  }else {
    dLinkedList->current = dLinkedList->current->previous;
    return dLinkedList->current->data;
  }
}


/**
 * getSize
 *
 * @return  the size
 */

int getSize(DLinkedList* dLinkedList){
  return dLinkedList->size;
}