Advertisement
Guest User

Untitled

a guest
Mar 18th, 2018
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.90 KB | None | 0 0
  1. // DLList.c - Implementation of doubly-linked list ADT
  2. // Written by John Shepherd, March 2013
  3. // Modified by John Shepherd, August 2014, August 2015
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <assert.h>
  9. #include "DLList.h"
  10.  
  11. // data structures representing DLList
  12.  
  13. typedef struct DLListNode {
  14.     char   *value;  // value of this list item (string)
  15.     struct DLListNode *prev;
  16.                    // pointer previous node in list
  17.     struct DLListNode *next;
  18.                    // pointer to next node in list
  19. } DLListNode;
  20.  
  21. typedef struct DLListRep {
  22.     int  nitems;      // count of items in list
  23.     DLListNode *first; // first node in list
  24.     DLListNode *curr;  // current node in list
  25.     DLListNode *last;  // last node in list
  26. } DLListRep;
  27.  
  28. // create a new DLListNode (private function)
  29. static DLListNode *newDLListNode(char *it)
  30. {
  31.     DLListNode *new;
  32.     new = malloc(sizeof(DLListNode));
  33.     assert(new != NULL);
  34.     new->value = strdup(it);
  35.     new->prev = new->next = NULL;
  36.     return new;
  37. }
  38.  
  39. // create a new empty DLList
  40. DLList newDLList()
  41. {
  42.     struct DLListRep *L;
  43.  
  44.     L = malloc(sizeof (struct DLListRep));
  45.     assert (L != NULL);
  46.     L->nitems = 0;
  47.     L->first = NULL;
  48.     L->last = NULL;
  49.     L->curr = NULL;
  50.     return L;
  51. }
  52.  
  53. // free up all space associated with list
  54. void freeDLList(DLList L)
  55. {
  56.     assert(L != NULL);
  57.     DLListNode *curr, *prev;
  58.     curr = L->first;
  59.     while (curr != NULL) {
  60.         prev = curr;
  61.         curr = curr->next;
  62.         free(prev->value);
  63.         free(prev);
  64.     }
  65.     free(L);
  66. }
  67.  
  68. // trim off \n from strings (private function)
  69. // this is needed for getDLList() because of fgets()
  70. // alternatively, we could use the evil gets() function
  71. static char *trim(char *s)
  72. {
  73.     int end = strlen(s)-1;
  74.     if (s[end] == '\n') s[end] = '\0';
  75.     return s;
  76. }
  77.  
  78. // create an DLList by reading items from a file
  79. // assume that the file is open for reading
  80. // assume one item per line, line < 999 chars
  81. DLList getDLList(FILE *in)
  82. {
  83.     DLList L;
  84.     DLListNode *new;
  85.     char line[1000];
  86.  
  87.     L = newDLList();
  88.     while (fgets(line,1000,in) != NULL) {
  89.         char *value = strdup(trim(line));
  90.         new = newDLListNode(value);
  91.         if (L->last == NULL) {
  92.             L->first = L->last = new;
  93.         }
  94.         else {
  95.             L->last->next = new;
  96.             new->prev = L->last;
  97.             L->last = new;
  98.         }
  99.         L->nitems++;
  100.     }  
  101.     L->curr = L->first;
  102.     return L;
  103. }
  104.  
  105. // display list to file, one item per line
  106. // assumes that the file is open for writing
  107. void putDLList(FILE *out, DLList L)
  108. {
  109.     assert(out != NULL); assert(L != NULL);
  110.     DLListNode *curr;
  111.     for (curr = L->first; curr != NULL; curr = curr->next)
  112.         fprintf(out,"%s\n",curr->value);
  113. }
  114.  
  115. // check sanity of a DLList (for testing)
  116. int validDLList(DLList L)
  117. {
  118.     if (L == NULL) {
  119.         fprintf(stderr,"DLList is null\n");
  120.         return 0;
  121.     }
  122.     if (L->first == NULL) {
  123.         // list is empty; curr and last should be null
  124.         if (L->last != NULL || L->curr != NULL) {
  125.             fprintf(stderr,"Non-null pointers in empty list\n");
  126.             return 0;
  127.         }
  128.     }
  129.     else {
  130.         // list is not empty; curr and last should be non-null
  131.         if (L->last == NULL || L->curr == NULL) {
  132.             fprintf(stderr,"Null pointers in non-empty list\n");
  133.             return 0;
  134.         }
  135.     }
  136.     int count;
  137.     DLListNode *curr;
  138.     // check scanning forward through list
  139.     count = 0;
  140.     for (curr = L->first; curr != NULL; curr = curr->next) {
  141.         if (curr->prev != NULL && curr->prev->next != curr) {
  142.             fprintf(stderr, "Invalid forward link into node (%s)\n",curr->value);
  143.             return 0;
  144.         }
  145.         if (curr->next != NULL && curr->next->prev != curr) {
  146.             fprintf(stderr, "Invalid backward link into node (%s)\n",curr->value);
  147.             return 0;
  148.         }
  149.         count++;
  150.     }
  151.     if (count != L->nitems) {
  152.         fprintf(stderr, "Forward count mismatch; counted=%d, nitems=%d\n",
  153.                 count, L->nitems);
  154.         return 0;
  155.     }
  156.     // check scanning backward through list
  157.     count = 0;
  158.     for (curr = L->last; curr != NULL; curr = curr->prev) {
  159.         count++;
  160.     }
  161.     if (count != L->nitems) {
  162.         fprintf(stderr, "Backward count mismatch; counted=%d, nitems=%d\n",
  163.                 count, L->nitems);
  164.         return 0;
  165.     }
  166.     // nothing went wrong => must be ok
  167.     return 1;
  168. }
  169.  
  170. // return item at current position
  171. char *DLListCurrent(DLList L)
  172. {
  173.     assert(L != NULL); assert(L->curr != NULL);
  174.     return L->curr->value;
  175. }
  176.  
  177. // move current position (+ve forward, -ve backward)
  178. // return 1 if reach end of list during move
  179. // if current is currently null, return 1
  180. int DLListMove(DLList L, int n)
  181. {
  182.     assert(L != NULL);
  183.     if (L->curr == NULL)
  184.         return 1;
  185.     else if (n > 0) {
  186.         while (n > 0 && L->curr->next != NULL) {
  187.             L->curr = L->curr->next;
  188.             n--;
  189.         }
  190.     }
  191.     else if (n < 0) {
  192.         while (n < 0 && L->curr->prev != NULL) {
  193.             L->curr = L->curr->prev;
  194.             n++;
  195.         }
  196.     }
  197.     return (L->curr == L->first || L->curr == L->last) ? 1 : 0;
  198. }
  199.  
  200. // move to specified position in list
  201. // i'th node, assuming first node has i==1
  202. int DLListMoveTo(DLList L, int i)
  203. {
  204.     assert(L != NULL); assert(i > 0);
  205.     L->curr = L->first;
  206.     return DLListMove(L, i-1);
  207. }
  208.  
  209.  
  210.  
  211. // insert an item before current item
  212. // new item becomes current item
  213. void DLListBefore(DLList L, char *it)
  214. {  
  215.     // assert pointer to struct is not NULL
  216.     // new is initialised and malloc'd space and value is stored into.
  217.     assert(L != NULL);
  218.     DLListNode *new = newDLListNode(it);
  219.  
  220.     // if list is empty...
  221.     // set current and it's pointers up as a lone item on the list.
  222.     if (L->curr == NULL){
  223.     L->first = L->last = L->curr = new;
  224.     new->next = new->prev = NULL;
  225.  
  226.     // if it first in the list, insert before
  227.     // set up new node pointers accordingly
  228.     } else if (L->curr == L->first){
  229.         new->next = L->curr;
  230.         new->prev = NULL;
  231.  
  232.         L->curr->prev = new;
  233.         L->first = L->curr = new;
  234.  
  235.     // else insert before node
  236.     } else {
  237.         new->next = L->curr;
  238.         new->prev = L->curr->prev;
  239.  
  240.         L->curr->prev->next = new;
  241.         L->curr->prev = new;
  242.         L->curr = new;  
  243.     }  
  244.  
  245.     L->nitems++;
  246.  
  247.    
  248.    // printing curr->prev when curr->prev points to NULL will cause a seg fault.
  249.    // fprintf(stdout,"previous to current: %s\n",curr->prev->value);
  250. }
  251.  
  252. // insert an item after current item
  253. // new item becomes current item
  254. void DLListAfter(DLList L, char *it)
  255. {
  256.     assert(L != NULL);
  257.     DLListNode *new = newDLListNode(it);
  258.  
  259.     // if the current list is empty
  260.     // set L pointers to new
  261.     // next and prev pointers to NULL
  262.     if (L->curr == NULL){
  263.         L->curr = L->first = L->last = new;
  264.         new->next = new->prev = NULL;
  265.  
  266.     // if current node is last in list
  267.     // append node to last node
  268.     } else if (L->curr == L->last){
  269.         new->next = NULL;
  270.         new->prev = L->curr;
  271.  
  272.         L->curr->next = new;
  273.         L->curr = new;
  274.         L->last = new;
  275.     // else it is the case of place a node
  276.     // between two existing nodes...
  277.     } else {
  278.         new->next = L->curr->next;
  279.         new->prev = L->curr;
  280.  
  281.         L->curr->next->prev = new;
  282.         L->curr->next = new;
  283.         L->curr = new;
  284.     }
  285.  
  286.     L->nitems++;
  287. }
  288.  
  289. // delete current item
  290. // new item becomes item following current
  291. // if current was last, current becomes new last
  292. // if current was only item, current becomes null
  293. void DLListDelete(DLList L)
  294. {
  295.     // make sure L exists
  296.     assert (L != NULL);
  297.  
  298.     // return, if current node is pointing to NULL
  299.     if (L->curr == NULL){
  300.         return;
  301.  
  302.         // if we are down to the last node in list
  303.         // ie, first and last are the same node
  304.         // if so, delete node and set curr, first and last to NULL
  305.     } else if (L->first == L->last){
  306.         // char pointer needs to be released as it
  307.         // was malloc'd with strdup()
  308.         free(L->curr->value);
  309.         free(L->curr);
  310.         L->curr = NULL;
  311.         L->first = NULL;
  312.         L->last = NULL;
  313.         // otherwise, if current node is last
  314.     } else if (L->curr == L->last){
  315.         //set previous node's next to NULL
  316.         // and set L->last to previous node
  317.         // as we are deleting the node which was previously last
  318.         L->last = L->curr->prev;
  319.         L->curr->next = NULL;
  320.         free(L->curr->value);
  321.         free(L->curr);
  322.         //reset current node to the new L->last
  323.         L->curr = L->last;
  324.         // otherwise, check if current is first.
  325.     } else if (L->curr == L->first){
  326.         // set L->first to next node
  327.         L->first=L->curr->next;
  328.         L->curr->prev = NULL;
  329.         // free current node
  330.         free(L->curr->value);
  331.         free(L->curr);
  332.         //reset current node
  333.         // so it is first on the list and the pointer to previous
  334.         // node points to NULL
  335.         L->curr = L->first;
  336.         // else it is neither only node, last node or first node
  337.         // so we are deleting in the middle of the list of 3 or more
  338.     } else {
  339.         // reseting current values and create a temp
  340.         // node for the new current node.
  341.         // free deleted nodes
  342.         // set current node to curr->next with temp node
  343.         L->curr->next->prev = L->curr->prev;
  344.         L->curr->prev->next = L->curr->next;
  345.         DLListNode *newCurr = L->curr->next;
  346.         free(L->curr->value);
  347.         free(L->curr);
  348.         L->curr = newCurr;
  349.     }
  350.     L->nitems--;
  351. }
  352.  
  353.  
  354. // return number of elements in a list
  355. int DLListLength(DLList L)
  356. {
  357.     return (L->nitems);
  358. }
  359.  
  360. // is the list empty?
  361. int DLListIsEmpty(DLList L)
  362. {
  363.     return (L->nitems == 0);
  364. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement