I cannot print delete_first result in C (circular linkedlist) - c

I want to print delete_first result and delete_last result. But it can only print delete_last code. How can i solve this matter?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int element;
typedef struct ListNode {
element data;
struct ListNode* link;
} ListNode;
void print_list(ListNode* head)
{
ListNode* p;
if (head == NULL) return;
else {
p = head->link;
do {
printf("%d ", p->data);
p = p->link;
} while (p != head->link);
}printf("\n");
}
ListNode* insert_first(ListNode* head, element data)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = data;
if (head == NULL) {
head = node;
node->link = head;
}
else {
node->link = head->link;
head->link = node;
}
return head;
}
ListNode* insert_last(ListNode* head, element data)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = data;
if (head == NULL) {
head = node;
node->link = head;
}
else {
node->link = head->link;
head->link = node;
head = node;
}
return head;
}
I want to print delete_first result and delete_last result. But I can only print delete_last result. How can i print delete_first result?
This is my delete_first code.
ListNode* delete_first(ListNode* head) {
if (head == NULL)
{
return head;
}
if (head->link == head) {
free(head);
head = NULL;
return head;
}
ListNode* p = head->link;
head->link = p->link;
free(head);
head = NULL;
return head;
}
ListNode* delete_last(ListNode* head) {
if (head == NULL)
return head;
ListNode* p = head->link;
if (head->link == head) {
free(head);
head = NULL;
return head;
}
while (p->link != head) {
p = p->link;
}
p->link = head->link;
free(head);
head = p;
return head;
}
int main() {
ListNode* head = NULL;
head = insert_first(head, 10);
head = insert_first(head, 20);
head = insert_first(head, 30);
head = insert_first(head, 40);
head = insert_last(head, 50);
print_list(head);
head=delete_last(head);
print_list(head);
head = delete_first(head);
print_list(head);
return 0;
}

If you want to print the element being removed, then you cannot free() it, or you have to copy it to a local variable and return it by value.
If you want caller to be able to print what remains of the list, then you need to find the last node which has a link that points at head and have it point at head->next instead. Then return that value (instead of NULL):
ListNode* delete_first(ListNode* head) {
if(!head)
return NULL;
if(head == head->link) {
free(head);
return NULL;
}
ListNode* last;
for(last = head; last->link != head; last = last->link);
last->link = head->link;
free(head);
return last->link;
}
There is no point of setting head = NULL as the copy of that variable is lost the caller anyways.

Related

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

What is the problem with this piece of code?

I am writing for deleting the last node of a doubly linked list. But, every time this function is giving me segmentation fault when I have 2 or more than 2 elements in the list.
void deleteEnd()
{
struct node *ptr;
if(head==NULL)
printf("\nList is empty.First add some numbers");
else if(head->next==NULL)
{
head = NULL;
free(head);
}
else
{
ptr = head;
while(ptr->next != NULL)
{
ptr = ptr -> next;
}
ptr -> prev -> next = NULL;
free(ptr);
}
}
Normally, when you are deleting a node from a linked list it is a good practice to pass a reference to the first node of the list as an argument of the function. In your case you are not showing us where the head is coming from, and I think that it could be quite a useful info, and I bet that the error hides there.
That is how the implementation could look like:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// insert end node: this is for testing purposes
struct node *insertEnd(struct node *head, int value) {
struct node *ptr, *new_node;
ptr = head;
new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = value;
new_node->next = NULL;
// The list is empty
if (head == NULL) {
head = new_node;
return head;
}
// Non empty list
while (ptr->next != NULL) {
ptr = ptr->next;
}
ptr->next = new_node;
return head;
}
// delete end node
struct node *deleteEnd(struct node *head) {
struct node *ptr, *preptr;
ptr = head;
preptr = NULL;
// The list is empty
if (head == NULL) {
printf("The list is empty. Nothing to delete.\n");
return head;
}
while(ptr->next != NULL) {
preptr = ptr;
ptr= ptr->next;
}
free(ptr);
if (preptr == NULL) {
head = NULL;
}
else {
preptr->next = NULL;
}
return head;
}
int main(void) {
struct node *llist;
llist = NULL;
llist = insertEnd(llist, 10);
llist = insertEnd(llist, 20);
llist = insertEnd(llist, 30);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
return 0;
}
It is always a great idea to maintain a global variable head and update it after every push/pop. See this:
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
struct node *deleteEnd(struct node *start)
{
struct node *ptr = start;
if(ptr==NULL)
{
printf("\nList is empty!!!");
return start;
}
else if(ptr->next == NULL)
{
free(ptr);
start = NULL;
return start;
}
else
{
while((ptr->next)->next!=NULL) //by doing this you dont have to maintain a prev pointer
{
ptr=ptr->next;
}
struct node *temp = ptr->next;
free(temp);
ptr->next = NULL;
return start;
}
}
Hope this helps!!!

Linked List output not showing correctly

I can't figure out where is the problem in my code:
typedef struct list List;
struct list {
int data;
List* next;
};
void insert_sorted(List** head, int value);
int main() {
List* head = NULL;
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
insert_sorted(&head, 3);
insert_sorted(&head, 2);
insert_sorted(&head, 40);
insert_sorted(&head, 10);
//insert_sorted(&head, 40);
List* temp = head;
while (temp != NULL) {
printf("%d\t", temp->data);
temp = temp->next;
}
printf("\n\n");
return 0;
}
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) {
node->next = *head;
*head = node;
} else {
temp = *head;
while (temp->next != NULL) {
if (temp->data < value && (temp->next)->data > value) {
node->next = temp->next;
temp->next = node;
} else
temp = temp->next;
}
temp->next = node;
}
}
1:
Run the code and see results. (Running and running...) after sorting data it is repeating some values forever.
2:
Go to
//insert_sorted(&head, 40);
this line an remove comment symbols.
Run the code and mark the result.(Time limit exceeded)
3:
Find this and remove comments:
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
Run and see results; (Again some problems)
Finally:
Remove all comments symbols and run it, this time it is working without any error but not as expected (List is not sorted correctly);
But why this is happening? Any help will be appreciated, and I am not at home at this but a learner.
Your void insert_sorted(List** head, int value) function is doing too much work.
void insert_sorted(List** head, int value) {
List* node = malloc(sizeof *node);
node->data = value;
for( ; *head ; head = &(*head)->next) {
if ((*head)->data > value) break; // we should insert before *head
}
// When we get here *head points to the pointer that needs to get node's value
// This can either be the original head (as supplied as argument tothe function)
// or some of the -> next pointers, or even the last ->next pointer.
node->next = *head;
*head = node;
}
The problem can be fixed as follows. If the node is inserted in the middle, the function can return and does not need to append the value at the end.
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) { // <-- fix
node->next = *head;
*head = node;
}
else {
temp = *head;
while (temp->next != NULL) {
if ( (temp->next)->data > value ) {
node->next = temp->next;
temp->next = node;
return; // <-- fix
}
else
temp = temp->next;
}
temp->next = node;
}
}
Your code sometimes inserted value twice (when value was not placed at the end of the list). This should fix the problem:
while(temp->next != NULL)
{
if(temp->data < value && (temp->next)->data > value)
{
node->next = temp->next;
temp->next = node;
break;
}
else
temp = temp->next;
}
if(temp->next == NULL)
temp->next = node;

Reverse a linked list in c

void reverse(node *pointer) {
node *head, *curr;
head = pointer;
curr = head;
while (head != NULL) {
while (curr -> next != NULL) {
curr = curr -> next;
}
printf("%d", curr -> data);
free(curr);
curr = head;
}
}
I don't know what's wrong with the code it prints only the last node of the linked list while trying to reverse it.
Simply:
node *reverse(node *head){
node *result = NULL;
while (head) {
node *next = head->next;
head->next = result;
result = head;
head = next;
}
return result;
}
You will not be able to see the output of the above function mainly for two reasons
Passing by value instead of reference.
No print statement inside the function. The effect of this function will be destroyed as soon as it comes out of the function.
In code:
void reverse(struct node** head_ref) {
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}

Doubly Linked list not working properly, C

#include <stdio.h>
#include <stdlib.h>
typedef struct list_item {
int value;
struct list_item *next;
struct list_item *prev;
} list_item_t;
typedef struct single_list {
list_item_t *head;
list_item_t *tail;
} slist_t;
void init(slist_t *list) {
list->head = NULL;
list->tail = NULL;
}
void add(slist_t *list, int value) {
list_item_t *newNode = (list_item_t *)malloc(sizeof(list_item_t));
// Case for empty list
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
newNode->value = value;
newNode->prev = NULL;
newNode->next = NULL;
}
// Case for nonempty list
else {
newNode->prev = list->tail;
newNode->value = value;
newNode->next = NULL;
list->tail = newNode;
}
}
void print(slist_t *list) {
if (list->head == NULL) {
printf("The list is empty\n");
return;
}
list_item_t *currentNode = list->head;
while (currentNode != NULL) {
printf("%d ", currentNode->value);
currentNode = currentNode->next;
}
printf("\n");
}
int main() {
slist_t myList;
init(&myList);
add(&myList, 5);
add(&myList, 2);
add(&myList, 6);
print(&myList);
}
Ok I got rid of my bus error but now when I try to print my list all it prints out is:
1
Is the problem in init function or my add function? I was wondering if since I don't use malloc in the init function that the list gets erased after every function call of add? Is that true? I have tried allocating it like this:
slist_t *list = (slist_t *)malloc(sizeof(slist_t))
but it gives me an error.
Failing to link old tail's next to the new tail.
// Case for nonempty list
else {
// Add. `list->tail->next` should be NULL before this code.
list->tail->next = newNode;
newNode->prev = list->tail;
newNode->value = value;
newNode->next = NULL;
list->tail = newNode;
}

Resources