Segmentation Fault Binary Tree Traversal - c

So i've been running and testing my code and everything seemed to have been working until i added 2 more functions for Pre-order and Post-order traversals of my tree.
The assignment was to create a linked list and tree for an input file with a random set of numbers. The linked list and tree traversals all need to be printed out in separate functions and i can't find where i went wrong.
i keep getting
Segmentation Fault (core dumped)
Here is my code:
//Tristan Shepherd
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct node
{
int num;
struct node *next;
};
struct tree
{
int numt;
struct tree *left;
struct tree *right;
};
typedef struct node LINK;
typedef struct tree branch;
int searchList(int number, LINK *head)
{
LINK *current;
current = head;
while (current != NULL)
{
if (current->num == number)
return 1; // Found it.
current = current->next;
}
return 0; // Did not find it.
}
LINK *insertList(int number, LINK *head)
{
LINK *current, *temp;
if (searchList(number, head) == 1) return head;
temp = (LINK *)malloc(sizeof(LINK));
temp->num = number;
if (head == NULL)
{
head = temp;
temp->next = NULL;
return head;
}
current = head;
if (current->num == number)
{
temp->next = current;
head = temp;
return head;
}
current = head;
while (current != NULL)
{
if (current->next == NULL || current->next->num == number)
{
temp->next = current->next;
current->next = temp;
return head;
}
current = current->next;
}
}
void printList(LINK *head)
{
LINK *current;
current = head;
while (current != NULL)
{
printf("%i\n", current->num);
current = current->next;
}
}
LINK *freeList(LINK *head)
{
LINK *current, *temp;
current = head;
while (current != NULL)
{
temp = current;
current = current->next;
free(temp);
}
free(head);
head = NULL;
return head;
}
void freeTree(branch *leaf)
{
if(leaf != 0)
{
freeTree(leaf->left);
freeTree(leaf->right);
free(leaf);
}
}
void insert(int new, branch **leaf)
{
if(*leaf == 0)
{
*leaf = (struct tree*) malloc(sizeof(struct tree));
(*leaf)->numt = new;
(*leaf)->left = 0;
(*leaf)->right = 0;
}
else if(new < (*leaf)->numt)
{
insert(new, &(*leaf)->left);
}
else if(new > (*leaf)->numt)
{
insert(new, &(*leaf)->right);
}
}
void printInorder(branch *leaf)
{
if (leaf == NULL)
return;
printInorder(leaf->left);
printf("%i ", leaf->numt);
printInorder(leaf->right);
}
void printPreorder(branch *leaf)
{
if (leaf == NULL)
return;
printf("%i ", leaf->numt);
printInorder(leaf->left);
printInorder(leaf->right);
}
void printPostorder(branch *leaf)
{
if (leaf == NULL)
return;
printInorder(leaf->left);
printInorder(leaf->right);
printf("%i ", leaf->numt);
}
int main (void)
{
int t;
FILE *stream = fopen("hw9.data", "r");
LINK *head;
branch *leaf;
head = NULL;
int number;
while (1)
{
fscanf(stream, "%i", &number);
if (feof(stream)) break;
insert(number, &leaf);
head = insertList(number, head);
}
fclose(stream);
printf("\nPrinting List: \n");
printList(head);
printf("\n\nPrinting in order\n");
printInorder(leaf);
printf("\n\nPrinting Pre order\n");
printPreorder(leaf);
printf("\n\nPrinting Post order\n");
printPostorder(leaf);
head = freeList(head);
freeTree(leaf);
head = NULL;
return 0;
}

branch *leaf; is not initialized. Your code expects leaf pointers to be NULL. Try branch *leaf = NULL;
Also, it looks like freeList frees head twice which is undefined behavior.

Related

Multiple data inside a single linked list node

Is it possible to have multiple data inside a single linked list node in C? And how do you input and access data with this?
#include <stdio.h>
#include <stdlib.h>
struct node{
int data;
char name[30];
struct node *next;
};
struct node *head, *tail = NULL;
void addNode(int data, char string) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
newNode->name[30] = string;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s", current->data, current->name);
current = current->next;
}
printf("\n");
}
int main()
{
char string1[10] = "Aaron";
char string2[10] = "Baron";
char string3[10] = "Carla";
addNode(9, string1);
addNode(7, string2);
addNode(2, string3);
printf("Original list: \n");
display();
sortList();
printf("Sorted list: \n");
display();
return 0;
}
I don't understand why my code didn't work. I was trying to make use of single linked list where it can accept/input and print/output the number and the name at the same time.
What I want it to happen is to print the number and the name.
The output should be:
Carla - 2
Baron - 7
Aaron - 9
Please read my comments marked as // CHANGE HERE.
// CHANGE HERE: accept a character array as argument
void addNode(int data, char string[]) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = data;
// CHANGE HERE: copy char array argument to name
strncpy(newNode->name, string, 30);
newNode->next = NULL;
if(head == NULL) {
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
void sortList() {
struct node *current = head, *index = NULL;
int temp;
char temp1[30];
if(head == NULL) {
return;
}
else {
while(current != NULL) {
index = current->next;
while(index != NULL) {
if(current->data > index->data) {
temp = current->data;
current->data = index->data;
index->data = temp;
// CHANGE HERE: swap the name along with data
strncpy(temp1, current->name, 30);
strncpy(current->name, index->name, 30);
strncpy(index->name, temp1, 30);
}
index = index->next;
}
current = current->next;
}
}
}
void display() {
struct node *current = head;
if(head == NULL) {
printf("List is empty \n");
return;
}
while(current != NULL) {
printf("%d - %s\n", current->data, current->name);
current = current->next;
}
printf("\n");
}

How to prevent the program to display the converted input, I'm wanting the program to display the original input

I want my code to display the original input 3 -> 2-> 1-> and not display the reversed one.
The output is displaying the 1-> 2-> 3-> . I want to see the original input without ruining the codes. How can I do that? Our professor taught us the concept of linked list and it is connected in this program to input a number and check if it is a palendrome
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
void insertNum(struct node** head, int number) {
struct node* temp = malloc(sizeof(struct node));
temp -> data = number;
temp -> next = *head;
*head = temp;
}
void display(struct node* head) {
struct node* printNode = head;
printf("displaying list1...\n");
printf("displaying the converted list..\n");
while (printNode != NULL) {
if (printNode->next)
printf("%d->",printNode->data);
else
printf("%d->NULL\n",printNode->data);
printNode=printNode->next;
}
}
struct node* reverseLL(struct node* head) {
struct node* reverseNode = NULL, *temp;
if (head == NULL) {
printf("\nThe list is empty.\n\n");
exit(0);
}
while (head != NULL) {
temp = (struct node*) malloc(sizeof(struct node));
temp -> data = head -> data;
temp -> next = reverseNode;
reverseNode = temp;
head = head -> next;
}
return reverseNode;
}
int check(struct node* LLOne, struct node* LLTwo) {
while (LLOne != NULL && LLTwo != NULL) {
if (LLOne->data != LLTwo->data)
return 0;
LLOne = LLOne->next;
LLTwo = LLTwo->next;
}
return (LLOne == NULL && LLTwo == NULL);
}
void deleteList(struct node** display) {
struct node* temp = *display;
while (temp != NULL) {
temp = temp->next;
free(*display);
*display = temp;
}
}
int main() {
int inputNum, countRun = 0, loop;
char choice;
struct node* reverseList;
struct node* head = NULL;
do {
printf("%Run number : %d\n", ++countRun);
printf("Enter 0 to stop building the list, else enter any integer\n");
printf("Enter list to check whether it is a palindrome... \n");
do {
scanf("%d", &inputNum);
if (inputNum == 0)
break;
insertNum(&head, inputNum);
} while (inputNum != 0);
display(head);
reverseList = reverseLL(head);
if ((check(head, reverseList)) == 1)
printf("\nPalindrome list.\n\n");
else
printf("\nNot palindrome.\n\n");
deleteList(&head);
} while (countRun != 2);
system("pause");
return 0;
}
Your insertNum inserts at the front of the list.
You need a version that appends at the back of the list:
void
appendNum(struct node **head, int number)
{
struct node *temp = malloc(sizeof(struct node));
struct node *cur;
struct node *prev;
temp->data = number;
// find tail of the list
prev = NULL;
for (cur = *head; cur != NULL; cur = cur->next)
prev = cur;
// append after the tail
if (prev != NULL)
prev->next = temp;
// insert at front (first time only)
else
*head = temp;
}
Here is the full code:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
void
appendNum(struct node **head, int number)
{
struct node *temp = malloc(sizeof(struct node));
struct node *cur;
struct node *prev;
temp->data = number;
// find tail of the list
prev = NULL;
for (cur = *head; cur != NULL; cur = cur->next)
prev = cur;
// append after the tail
if (prev != NULL)
prev->next = temp;
// insert at front (first time only)
else
*head = temp;
}
void
insertNum(struct node **head, int number)
{
struct node *temp = malloc(sizeof(struct node));
temp->data = number;
temp->next = *head;
*head = temp;
}
void
display(struct node *head)
{
struct node *printNode = head;
printf("displaying list1...\n");
printf("displaying the converted list..\n");
while (printNode != NULL) {
if (printNode->next)
printf("%d->", printNode->data);
else
printf("%d->NULL\n", printNode->data);
printNode = printNode->next;
}
}
struct node *
reverseLL(struct node *head)
{
struct node *reverseNode = NULL,
*temp;
if (head == NULL) {
printf("\nThe list is empty.\n\n");
exit(0);
}
while (head != NULL) {
temp = (struct node *) malloc(sizeof(struct node));
temp->data = head->data;
temp->next = reverseNode;
reverseNode = temp;
head = head->next;
}
return reverseNode;
}
int
check(struct node *LLOne, struct node *LLTwo)
{
while (LLOne != NULL && LLTwo != NULL) {
if (LLOne->data != LLTwo->data)
return 0;
LLOne = LLOne->next;
LLTwo = LLTwo->next;
}
return (LLOne == NULL && LLTwo == NULL);
}
void
deleteList(struct node **display)
{
struct node *temp = *display;
while (temp != NULL) {
temp = temp->next;
free(*display);
*display = temp;
}
}
int
main()
{
int inputNum, countRun = 0, loop;
char choice;
struct node *reverseList;
struct node *head = NULL;
do {
printf("%Run number : %d\n", ++countRun);
printf("Enter 0 to stop building the list, else enter any integer\n");
printf("Enter list to check whether it is a palindrome... \n");
do {
scanf("%d", &inputNum);
if (inputNum == 0)
break;
#if 0
insertNum(&head, inputNum);
#else
appendNum(&head, inputNum);
#endif
} while (inputNum != 0);
display(head);
reverseList = reverseLL(head);
if ((check(head, reverseList)) == 1)
printf("\nPalindrome list.\n\n");
else
printf("\nNot palindrome.\n\n");
deleteList(&head);
} while (countRun != 2);
system("pause");
return 0;
}

Circular doubly linked list in C delete function

I have a circular doubly linked list.
The deletefront() function is not working: the output is wrong. What is the mistake?
The other functions are working. But I get a wrong output after displaying after calling deletefront function. The 100 value which should be deleted is still appearing. Please correct it.
I have included the C source code:
// circular doubly linked list
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *rlink;
struct node *llink;
} node;
node *head = NULL;
node *getnode(int ele) {
node *ptr;
ptr = (node *)malloc(sizeof(node));
if (ptr == NULL) {
printf("memory not alloc");
exit(0);
}
if (ptr != NULL) {
ptr->data = ele;
ptr->rlink = NULL;
ptr->llink = NULL;
}
return ptr;
}
void insertfront(int ele) {
node *newnode;
newnode = getnode(ele);
if (head == NULL) {
head = newnode;
head->rlink = head;
head->llink = head;
} else {
head->llink = newnode;
newnode->rlink = head;
head = newnode;
}
}
void insertend(int ele) {
node *newnode;
newnode = getnode(ele);
if (head == NULL) {
head = newnode;
head->rlink = head;
head->llink = head;
} else {
node *temp = head;
do {
temp = temp->rlink;
} while (temp != head->llink);
newnode->rlink = temp->rlink;
temp->rlink = newnode;
newnode->llink = temp;
}
}
int lenlist() {
node *temp;
int count = 0;
temp = head;
do {
temp = temp->rlink;
count++;
} while (temp != head);
return count;
}
void insertatpos(int ele,int pos) {
if (pos == 1) {
insertfront(ele);
} else
if (pos == (lenlist() + 1)) {
insertend(ele);
} else
if (pos > 1 && pos <= (lenlist() + 1)) {
node *prev, *curr;
node *newnode = getnode(ele);
int count = 1;
curr = head;//curr points to 1st node
do {
prev = curr;
count++;
curr = curr->rlink;
if (count == pos) {
prev->rlink = newnode;
newnode->llink = prev;
newnode->rlink = curr;
curr->llink = newnode;
}
} while (curr != head);
} else {
printf("invalid position");
}
}
void delfront() {
if (head == NULL)
printf("empty list");
node *aux;
node *lastnode, *secondnode;
aux = head;
lastnode = head->llink;
secondnode = head->rlink;
secondnode->llink = lastnode;
lastnode->rlink = secondnode;
free(aux);
head = secondnode;
}
void display() {
node *aux = head;
do {
printf("%d->", aux->data);
aux = aux->rlink;
} while (aux != head);
printf("\n");
}
int main() {
insertfront(100);
insertend(20);
printf("\n%d\n", lenlist());
insertatpos(45, 2);
display();
delfront();
display();
}
The problem is not in the deletefront() function, instead, you have missed updating a few links in the insertfront() and insertend() functions.
I have updated the code here and also added the comment where I made the changes. Try to visualise it using an example.
However, I suggest that you solve such issues using a debugger or go through the code with a sample test case. It will improve you debugging as well as coding skills!
Your code have a lot of mistakes.
// circular doubly linked list
#include <stdio.h>
#include <stdlib.h>
/*i changed the names of your pointers here*/
typedef struct node {
int data;
struct node *prev, *next;
} node;
/*
node *head = NULL;
This will be removed.
Avoid using globals as much as you can.
*/
/*
This function is unecessary.
node *createNode(int ele) {
node *ptr;
ptr = (node *)malloc(sizeof(node));
if (ptr == NULL) {
printf("memory not alloc");
exit(0);
}
if (ptr != NULL) {
ptr->data = ele;
ptr->rlink = NULL;
ptr->llink = NULL;
}
return ptr;
}
*/
char insertFront(node **head, int ele) {
node *newNode=malloc(sizeof(node));
If (newNode==NULL) return 0;
newNode->data=ele;
if (*head){
newNode->next=*head;
newNode->prev=(*head)->prev;
(*head)->prev->next=newNode;
(*head)->prev=newNode;
} else {
newNode->next=newNode;
newNode->prev=newNode;
}
*head=newNode;
return 1;
}
char insertEnd(node **head, int ele) {
node *newNode=malloc(sizeof(node));
If (newNode==NULL) return 0;
newNode->data=ele;
if (*head){
newNode->next=*head;
newNode->prev=(*head)->prev;
(*head)->prev->next=newNode;
(*head)->prev=newNode;
} else {
newNode->next=newNode;
newNode->prev=newNode;
*head=newNode;
}
return 1;
}
/*You could simple create a struct list that would have as members
the head of your list and its height to avoid calculating it each time
you want it but anyway. I will fix that.
int lenList(node *head) {
if (*head==NULL) return 0;
node *temp=head;
int count = 0;
do {
temp = temp->next;
count++;
} while (temp != head);
return count;
}
*/
char insertNatP(node **head, int ele, int pos) {
If (pos<1 || pos>lenList(head)){
printf("Invalid Position\n");
return 0;
}
int i;
for(i=0; i<pos-1; head=&head->next, i++);
node *newNode=malloc(sizeof(node));
If (newNode==NULL){
printf("Memory could not be allocated\n");
return 0;
}
newNode->data=ele;
If (*head!=NULL){
newNode->prev=(*head)->prev;
(*head)->prev->next=newNode;
(*head)->prev=newNode
newNode->next=*head;
} else {
newNode->prev=newNode;
newNode->next=newNode;
}
*head=newNode;
return 1;
}
char delFront(node **head) {
if (*head == NULL) return 0;
node garbage=*head;
*head=(*head)->next;
if (*head==garbage) *head=NULL; else{
(*head)->prev=garbage->prev;
garbage->prev->next=*head;
}
free(garbage);
return 1;
}
void printList(node *list) {
if (list==NULL) return;
node *sentinel=list->prev;
while (list!=sentinel) {
printf("%d->", list->data);
list=list->next;
}
printf("%d\n", list->data);
}
int main() {
node *l1=NULL;
insertFront(&l1, 100);
insertEnd(&l1, 20);
printf("\n%d\n", lenList(l1));
insertNatP(&l1, 45, 2);
printList(l1);
delFront(&l1);
printList(l1);
}
Try this

Saving pointer to last node in doubly linked list when performing insertion sort

Here I have a header file to include functions:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node** top, node* newNode, node** last) {
node* current;
if (*top == NULL) {
*top = newNode;
} else if ((*top)->data >= newNode->data) {
newNode->next = *top;
newNode->next->prev = newNode;
*top = newNode;
if ((*top)->next == NULL) {
*last = *top;
}
} else {
current = *top;
while (current->next != NULL &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
if (current->next != NULL) {
newNode->next->prev = newNode;
}
current->next = newNode;
newNode->prev = current;
}
if ((*top)->next == NULL) {
*last = *top;
}
}
void insertionSort(node** top, node** last) {
node* sorted = NULL;
node* current = *top;
while (current != NULL) {
node* next = current->next;
current->prev = current->next = NULL;
sortedInsert(&sorted, current, last);
current = next;
}
*top = sorted;
}
node* deleteByPos(node* list, node** last, int position) {
int c = 0;
node* temp;
node* prev;
temp=list;
if (temp==NULL) {
printf("No nodes available to delete\n\n");
return list;
} else {
while(temp!=NULL && c != position) {
prev=temp;
temp=temp->next;
c++;
}
if (temp==NULL) {
printf("Reached end of list, position not available\n\n");
return list;
} else if (temp->next == NULL) {
prev->next=temp->next;
*last = prev;
free(temp);
return list;
} else {
prev->next=temp->next;
temp->next->prev = prev;
free(temp);
return list;
}
}
}
node* makeNode(int n) {
node* np = malloc(sizeof (node));
np->data = n;
np->prev = NULL;
np->next = NULL;
return np;
}
void printList(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->next;
}
}
void printListReverse(node* np) {
while (np != NULL) {
printf("%d\n", np->data);
np = np->prev;
}
}
#endif /* driver_h */
and a main file:
#include "driver.h"
int main() {
int n;
node* np;
node* top;
node* last;
printf("Enter integers to add to list\n");
do {
if (scanf("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
if (top == NULL) {
top = np;
} else {
last->next = np;
np->prev = last;
}
last = np;
}
} while (n != 0);
printf("\n\n");
printf("You entered:\n");
printList(top);
printf("\n\n");
printf("In reverse:\n");
printListReverse(last);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
top = deleteByPos(top, &last, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(last);
insertionSort(&top, &last);
printf("From top after sort:\n");
printList(top);
printf("In reverse after Sort:\n");
printListReverse(last);
}
What this program does is take user input of integers, stores them in a doubly linked list, deletes a node at a user defined point and then performs an insertion sort. What I am trying to do is save a pointer to the last node in the sortedInsert function with the following code:
if ((*top)->next == NULL) {
*last = *top;
}
However, if you enter 6 5 3 1 9 8 4 2 7 4 2, then delete at position 2, when printing in reverse it prints out 6 5 4 4 2 2 1. For some reason it skips over 9 7 8. I cannot figure out why or how to fix this. How can I do this properly?
With lists, it helps to draw a diagram for all the cases. It's natural to use induction on lists to prove your code is correct.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h> /* Asserting is useful when it come to lists especially. */
struct node {
struct node* next;
struct node* prev;
int data;
};
/* Saves you from dealing with 'top' and 'tail' every time. */
struct list {
struct node *head, *tail;
};
/* https://en.wikipedia.org/wiki/Insertion_sort */
void insertionSort(struct list* list) {
struct node* i = list->head, *j0, *j1;
while(i) {
j1 = i, j0 = j1->prev;
while(j0 && j0->data > j1->data) {
/* Swap. */
int temp = j0->data;
j0->data = j1->data;
j1->data = temp;
/* Decrement. */
j1 = j0;
j0 = j0->prev;
}
i = i->next;
}
}
/* Returns whether the position was deleted. */
int deleteByPos(struct list* list, int position) {
struct node* n;
assert(list);
/* Node n is the position's in the list. */
for(n = list->head; n && position; n = n->next, position--);
if (n==NULL) {
printf("No nodes available to delete\n\n");
return 0;
}
/* Fixme: If I'm not mistaken, there are 9 cases for you to be
mathematically certain this works, and I haven't tried them all.
Eg, 1 node, 2 nodes x2, 3 nodes x3, where the internal node is the 2nd of
the 3 nodes. */
if(n->prev == NULL) {
/* The first one. */
assert(list->head == n);
list->head = n->next;
if(n->next) n->next->prev = NULL;
} else {
/* Skip over. */
n->prev->next = n->next;
}
if(n->next == NULL) {
/* The last one. */
assert(list->tail == n);
list->tail = n->prev;
if(n->prev) n->prev->next = NULL;
} else {
/* Skip over. */
n->next->prev = n->prev;
}
n->prev = n->next = NULL; /* Helps in debugging. */
free(n);
return 1;
}
struct node* makeNode(struct list *list, int n) {
struct node* np = malloc(sizeof *np);
if(!np) return 0;
np->data = n;
np->prev = list->tail;
np->next = NULL;
/* Push it in the list. */
if(list->tail) {
assert(list->head != NULL && list->tail->next == NULL);
list->tail->next = np;
} else {
/* The first one. */
assert(list->head == NULL && list->tail == NULL);
list->head = np;
}
list->tail = np;
return np;
}
void printList(const struct list*const list) {
const struct node *n = list->head;
while (n) {
printf("%d\n", n->data);
n = n->next;
}
}
void printListReverse(const struct list*const list) {
const struct node *n = list->tail;
while (n) {
printf("%d\n", n->data);
n = n->prev;
}
}
int main(void) {
int n;
struct list list = { 0, 0 };
printf("Enter integers to add to list\n");
while(scanf("%d", &n) == 1 && n)
if(!makeNode(&list, n)) return perror("node"), EXIT_FAILURE;
printf("\n\n");
printf("You entered:\n");
printList(&list);
printf("\n\n");
printf("In reverse:\n");
printListReverse(&list);
printf("\n\n");
printf("Enter a position to delete:");
scanf("%d", &n);
printf("You entered %d.\n", n);
deleteByPos(&list, n);
printf("\n\n");
printf("In reverse after delete:\n");
printListReverse(&list);
insertionSort(&list);
printf("From top after sort:\n");
printList(&list);
printf("In reverse after Sort:\n");
printListReverse(&list);
return EXIT_SUCCESS;
}
*One would ideally free memory on exit.
It is usually much simpler to use a sentinel node rather than NULL to indicate the end of a list. So an empty list consists of a node whose head and tail point to itself. Once you add elements, sentinel->next is the first in the list and sentinel->prev is the last in the list. This removes many of the cases you have to test for NULL in your code:
#ifndef driver_h
#define driver_h
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
typedef struct nodePtrs nodePtrs;
struct node {
node* next;
node* prev;
int data;
};
void sortedInsert(node* top, node* newNode) {
node* current = top;
while (current->next != top &&
current->next->data < newNode->data) {
current = current->next;
}
newNode->next = current->next;
newNode->next->prev = newNode;
current->next = newNode;
current->next->prev = current;
}
void insertionSort(node* top) {
node* current = top->next;
// make top an empty ring so can append to it
top->next = top->prev = top;
while (current != top) {
node* next = current->next;
sortedInsert(top, current);
current = next;
}
}
node* deleteByPos(node* top,int position) {
int c = 0;
node* temp = top->next;
while (true) {
if (temp == top) {
printf("Reached end of list, position not available\n\n");
return top;
}
if (c == position) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
return top;
}
temp = temp->next;
c++;
}
}
node* makeNode(int n) {
node* np = malloc(sizeof(node));
np->data = n;
np->prev = np;
np->next = np;
return np;
}
void printList(node* top) {
for (node* np = top->next; np != top; np = np->next) {
printf("%d\n", np->data);
}
}
void printListReverse(node* top) {
for (node* np = top->prev; np != top; np = np->prev) {
printf("%d\n", np->data);
}
}
#endif /* driver_h */
main file :
#include "driver.h"
int main() {
int n;
node* np;
node* top;
top= makeNode(0);
printf("Enter integers to add to list\n");
do {
if (scanf_s("%d", &n) != 1) {
n = 0;
}
if (n != 0) {
np = makeNode(n);
np->prev = top->prev;
top->prev = np;
top->prev->next = top;
np->prev->next = np;
}
} while (n != 0);

Linked list append doesn't work the last time

Why does the last append call not work? I have to add some garbage here because it is complaining that my post is mostly code, I hope it is enough details by now.
typedef struct node {
int val;
struct node * next;
} node_t;
void append_node(node_t * head, int val) {
node_t * current = head;
while(current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(node_t));
if(current->next == NULL)
printf("err");
current = current->next;
current->val = val;
current->next = NULL; //malloc(sizeof(node_t));
}
void print_list(node_t * head) {
node_t * current = head;
while(current->next != NULL) {
printf("%d ", current->val);
current = current->next;
}
printf("\n");
}
int main() {
node_t * list = malloc(sizeof(node_t));
list->val = 1;
list->next = NULL;
append_node(list,12);
append_node(list,14);
append_node(list,17);
print_list(list);
return 0;
}
Output:
1 12 14
The problem is in your print function. You don't print the last element.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node * next;
} node_t;
void append_node(node_t * head, int val) {
node_t * current = head;
while(current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(node_t));
if(current->next == NULL)
printf("err");
current = current->next;
current->val = val;
current->next = NULL; //malloc(sizeof(node_t));
}
void print_list(node_t * head) {
node_t * current = head;
while(current!= NULL) {
printf("%d ", current->val);
current = current->next;
}
printf("\n");
}
int main() {
node_t * list = malloc(sizeof(node_t));
list->val = 1;
list->next = NULL;
append_node(list,12);
append_node(list,14);
append_node(list,17);
print_list(list);
return 0;
}

Resources