Skip to content

Instantly share code, notes, and snippets.

@scottdriscoll
Created March 15, 2013 03:51
Show Gist options
  • Save scottdriscoll/5167361 to your computer and use it in GitHub Desktop.
Save scottdriscoll/5167361 to your computer and use it in GitHub Desktop.
simple doubly linked list in ansi c
#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