Created
March 15, 2013 03:51
-
-
Save scottdriscoll/5167361 to your computer and use it in GitHub Desktop.
simple doubly linked list in ansi c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
struct node { | |
int num; | |
struct node *next; | |
struct node *prev; | |
}; | |
struct node *create(int num) | |
{ | |
struct node *newnode; | |
newnode = (struct node *)malloc(sizeof(struct node)); | |
if (newnode == NULL) { | |
return NULL; | |
} | |
newnode->num = num; | |
newnode->prev = NULL; | |
newnode->next = NULL; | |
return newnode; | |
} | |
void push(struct node **list, int num) | |
{ | |
struct node *newnode = create(num); | |
if (newnode == NULL) { | |
return; | |
} | |
newnode->num = num; | |
newnode->next = *list; | |
if (*list != NULL) { | |
(*list)->prev = newnode; | |
} | |
*list = newnode; | |
} | |
int pop(struct node **list) | |
{ | |
struct node *tmp; | |
int val = -1; | |
if (*list != NULL) { | |
tmp = *list; | |
val = (*list)->num; | |
*list = (*list)->next; | |
if (*list != NULL) { | |
(*list)->prev = NULL; | |
} | |
free(tmp); | |
} | |
return val; | |
} | |
void insertAfter(struct node **list, struct node *current, int num) | |
{ | |
struct node *newnode; | |
newnode = create(num); | |
if (newnode == NULL) { | |
return; | |
} | |
if (*list == NULL) { | |
*list = newnode; | |
} else { | |
newnode->next = current->next; | |
newnode->prev = current; | |
if (current->next) { | |
current->next->prev = newnode; | |
} | |
current->next = newnode; | |
} | |
} | |
void deleteCurrent(struct node **list, struct node *current) | |
{ | |
if (*list == NULL || current == NULL) { | |
return; | |
} | |
if (*list == current) { | |
*list = (*list)->next; | |
if (*list != NULL) { | |
(*list)->prev = NULL; | |
} | |
} else { | |
current->prev->next = current->next; | |
if (current->next != NULL) { | |
current->next->prev = current->prev; | |
} | |
} | |
free(current); | |
} | |
void deleteAll(struct node *list) | |
{ | |
struct node *tmp; | |
while (list != NULL) { | |
tmp = list; | |
list = list->next; | |
free(tmp); | |
} | |
} | |
/* | |
Callback function that qsort() calls. | |
*/ | |
int __sortFunc(const void *n1, const void *n2) | |
{ | |
struct node **node1 = (struct node **)n1, **node2 = (struct node **)n2; | |
if ((*node1)->num < (*node2)->num) { | |
return -1; | |
} | |
if ((*node1)->num > (*node2)->num) { | |
return 1; | |
} | |
return 0; | |
} | |
void sort(struct node **list) | |
{ | |
int nodeCount = 0, i; | |
struct node **tmpList = NULL, *tmp; | |
if (*list == NULL) { | |
return; | |
} | |
tmp = *list; | |
while (tmp != NULL) { | |
nodeCount++; | |
tmp = tmp->next; | |
} | |
/* | |
Create a temporary array to hold our list | |
Normally, I would save this array for reuse later, and resize it if necessary. | |
*/ | |
tmpList = (struct node **)malloc(sizeof(struct node *) * nodeCount); | |
if (tmpList == NULL) { | |
return; | |
} | |
for (i = 0, tmp = *list; i < nodeCount; i++) { | |
tmpList[i] = tmp; | |
tmp = tmp->next; | |
} | |
qsort((void *)tmpList, nodeCount, sizeof(struct node *), __sortFunc); | |
/* Reconstruct list */ | |
for (i = 0; i < nodeCount; i++) { | |
tmp = tmpList[i]; | |
if (i == 0) { | |
*list = tmpList[0]; | |
(*list)->prev = NULL; | |
} else { | |
tmpList[i]->prev = tmpList[i-1]; | |
} | |
if (i + 1 < nodeCount) { | |
tmpList[i]->next = tmpList[i+1]; | |
} else { | |
tmpList[i]->next = NULL; | |
} | |
} | |
free(tmpList); | |
} | |
void display(struct node *list, struct node *current) | |
{ | |
while (list != NULL) { | |
printf("%d", list->num); | |
if (list == current) { | |
printf("(c)"); | |
} | |
if (list->next != NULL) { | |
printf(" | "); | |
} | |
list = list->next; | |
} | |
printf("\n"); | |
} | |
void menu(void) | |
{ | |
printf("Main Menu\n"); | |
printf("\t1) Push new value\n"); | |
printf("\t2) Pop\n"); | |
printf("\t3) Display all\n"); | |
printf("\t4) Insert value after current\n"); | |
printf("\t5) Delete current\n"); | |
printf("\t6) Move current left\n"); | |
printf("\t7) Move current right\n"); | |
printf("\t8) Sort\n"); | |
printf("\t9) Quit\n"); | |
printf("\t0) Menu\n"); | |
} | |
int main(void) | |
{ | |
struct node *head = NULL, *current = NULL; | |
int input = 0, newNum; | |
menu(); | |
do { | |
printf("enter command: "); | |
scanf("%d", &input); | |
switch (input) { | |
case 1: | |
printf("enter integer: "); | |
scanf("%d", &newNum); | |
push(&head, newNum); | |
if (current == NULL) { | |
current = head; | |
} | |
display(head, current); | |
break; | |
case 2: | |
if (current != NULL && current == head) { | |
current = current->next; | |
} | |
newNum = pop(&head); | |
printf("got %d\n", newNum); | |
display(head, current); | |
break; | |
case 3: | |
display(head, current); | |
break; | |
case 4: | |
printf("enter integer: "); | |
scanf("%d", &newNum); | |
insertAfter(&head, current, newNum); | |
if (current == NULL) { | |
current = head; | |
} | |
display(head, current); | |
break; | |
case 5: | |
if (current != NULL) { | |
deleteCurrent(&head, current); | |
current = head; | |
} | |
display(head, current); | |
break; | |
case 6: | |
if (current && current->prev) { | |
current = current->prev; | |
} | |
display(head, current); | |
break; | |
case 7: | |
if (current && current->next) { | |
current = current->next; | |
} | |
display(head, current); | |
break; | |
case 8: | |
sort(&head); | |
display(head, current); | |
break; | |
case 9: | |
deleteAll(head); | |
break; | |
case 0: | |
menu(); | |
break; | |
} | |
fflush(stdin); | |
} while (input != 9); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment