I am trying to reverse a Doubly Linked List with no success. After reversing, the list appears to be empty.
Here is my implementation:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct Item Item;
typedef struct DLL DLL;
struct Item {
int value;
Item* next;
Item* prev;
};
struct DLL {
Item* head;
Item* tail;
int size;
void(*add)(DLL*, int);
void(*addToTail)(DLL*, int);
};
void add(DLL* list, int val) {
Item* new_item = (Item*) malloc(sizeof(Item));
if (new_item == NULL) {
exit(-1);
}
new_item->value = val;
new_item->next = list->head->next;
list->head->next = new_item;
new_item->prev = list->head;
list->size++;
}
void addToTail(DLL* list, int val) {
Item* new_item = (Item*) malloc(sizeof(Item));
if (new_item == NULL) {
exit(-1);
}
new_item->value = val;
new_item->prev = list->tail->prev;
list->tail->prev = new_item;
new_item->next = list->tail;
list->size++;
}
Item* find(DLL* list, int val) {
Item* iter = list->head->next;
while (iter != list->tail) {
if (iter->value == val) {
return iter;
}
iter = iter->next;
}
return NULL;
}
void reverse(DLL* list) {
Item* current = list->head;
Item* temp = NULL;
while (current != NULL) {
temp = current->next;
current->next = current->prev;
current->prev = temp;
current = current->prev;
}
temp = list->head;
list->head = list->tail;
list->tail = temp;
}
void printList(DLL* list) {
Item* iter = list->head->next;
while (iter != list->tail) {
printf("%d\n", iter->value);
iter = iter->next;
}
}
DLL* initDLL() {
DLL* list = (DLL*) malloc(sizeof(DLL));
if (list == NULL) {
exit(-1);
}
// Creating head & tail
list->head = (Item*) malloc(sizeof(Item));
list->tail = (Item*) malloc(sizeof(Item));
if (list->head == NULL || list->tail == NULL) {
free(list);
exit(-1);
}
// Initializing head & tail values just for testing
list->head->value = 100;
list->tail->value = 200;
list->head->prev = NULL;
list->head->next = list->tail;
list->tail->prev = list->head;
list->tail->next = NULL;
list->size = 0;
list->add = add;
list->addToTail = addToTail;
return list;
}
int main() {
DLL* my_list = initDLL();
my_list->add(my_list, 1);
my_list->add(my_list, 2);
my_list->add(my_list, 3);
printList(my_list);
// Outputs:
// 3
// 2
// 1
reverse(my_list);
printList(my_list);
// Prints nothing since list->head->next == list->tail
}
I expected
3
2
1
1
2
3
but get only
3
2
1
The first printList() works as expected, but the second produces no output.
Looking into the problem I've found that after reversing the list, for some reason list->head->next is pointing to list->tail, even though there are 3 elements in the list.
I've searched online for examples but stumbled upon implementations which don't use a DLL structure such as mine, but only Node structure.
In your add function, you need to set new_item->next->prev to new_item after setting new_item->next = list->head->next;
void add(DLL* list, int val) {
Item* new_item = malloc(sizeof *new_item);
if (new_item == NULL) {
exit(EXIT_FAILURE);
}
new_item->value = val;
new_item->next = list->head->next;
new_item->next->prev = new_item; // <--- This is missing in your code
list->head->next = new_item;
new_item->prev = list->head;
list->size++;
}
Similar issue is in your addToTail(). There you need to set new_item->prev->next to new_item.
Related
ok, now i have to make double linked list on c.
there are 7 functions which act on main.
append.
insertAt.
deleteAt.
print.
print_revers.
newnode.
newDLL.
i can amend only 5 functions
append, insertAt, deleteAt, print, print_reverse
finally i can make append,print,print_reverse
however, i can't make insertAt,deleteAt, because of index.
1. i can't understand why the code
else {
while (index-- >= 0) {
temp = temp->next;
}
make memory collide. for using index, i need to move node to collect position and connect to newnode. but it doesn't work...
2. also what's return; 's role? i have not seen such type of return.
3. how can i make deleteAt using index? i think deleteAt and insertAt have quiet similar algoritum. so i try to make insertAt first and deleteAt last. but what i write doesn't work well..
i can find a lot of data of doublelinkedlist on internet. but i can't find using index.... i have been listening c language lecture on only two month, so sorry about the spagettii code...
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int val;
struct Node *prev;
struct Node *next;
} Node;
typedef struct {
Node *head;
int size;
} DLL;
Node *newnode(int n)
{
Node *temp = (Node *)malloc(sizeof(Node));
temp->val = n;
temp->prev = NULL;
temp->next = NULL;
return temp;
}
DLL *newDLL() {
DLL *temp = (DLL *)malloc(sizeof(DLL));
temp->head = NULL;
temp->size = 0;
return temp;
}
void append(DLL *list, Node *newnode) {
struct Node* temp = list->head;
struct Node* newNode = newnode;
if (list->head == NULL) {
list->head = newNode;
list->size++;
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
list->size++;
temp->next = newNode;
newNode->prev = temp;
}
void insertAt(DLL *list, int index, Node *newnode) {
struct Node* temp = (Node *)malloc(sizeof(Node));
if (index < 0 || index >= list->size + 1) {
printf("out of range\n");
}
else if (index == 0) {
newnode->next = list->head;
list->head->prev = newnode;
list->head = newnode;
}
else {
while (index-- >= 0) {
temp = temp->next;
}
temp->val = newnode->val;
temp->next = list->head->next;
list->head->next = temp;
temp->prev = list->head;
if (temp->next != NULL)
temp->next->prev = temp;
}
}
void deleteAt(DLL *list, int index) {
//save reference to first link
struct Node* temp = (Node *)malloc(sizeof(Node));
//if only one link
if (list->head->next == NULL) {
list->head->prev = NULL;
}
else {
list->head->next->prev = NULL;
}
list->head = list->head->next;
//return the deleted link
return;
}
void print(DLL *list) {
struct Node* temp = list->head;
printf("Forward: ");
while (temp != NULL) {
printf("[%d] ", temp->val);
temp = temp->next;
}
printf("\n");
}
void print_reverse(DLL *list) {
struct Node* temp = list->head;
if (temp == NULL) return; // empty list, exit
// Going to last Node
while (temp->next != NULL) {
temp = temp->next;
}
// Traversing backward using prev pointer
printf("Reverse: ");
while (temp != NULL) {
printf("[%d] ", temp->val);
temp = temp->prev;
}
printf("\n");
}
int main() {
DLL *list = newDLL();
int i;
for (i = 1; i < 6; i++) {
append(list, newnode(i));
}
print(list);
deleteAt(list, -1);
deleteAt(list, 5);
deleteAt(list, 0);
print(list);
deleteAt(list, 2);
print(list);
deleteAt(list, 2);
print(list);
insertAt(list, -1, newnode(6));
insertAt(list, 3, newnode(6));
insertAt(list, 0, newnode(7));
print(list);
insertAt(list, 1, newnode(8));
print(list);
insertAt(list, 4, newnode(9));
print(list);
print_reverse(list);
return 0;
}
The part where you insert at index has problems:
temp = malloc is wrong, it should start with temp = head.
in the insertion:
temp->val = newnode->val;
temp->next = list->head->next;
list->head->next = temp;
temp->prev = list->head;
temp->next should not be head->next, it should be newnode. newnode->next should be temp->next etc.
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;
#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;
}
I'm trying to sort a doubly linked list using a bubblesort in C. However, the list returned is the same list I put in. Example [1,2,4,8,0,3] -> [1,2,4,8,0,3]
void bublesort(slist_t *list){
list_item_t *curr = NULL;
curr = list->head;
if(curr == NULL){
printf("\nList is empty.");
}
while(curr->next != NULL && curr->value > curr->next->value){
curr = swap(curr, curr->next, list);
}
while(curr->prev != NULL){
if(curr->value < curr->prev->value){
bublesort(list);
}
}
}
list_item_t *swap(list_item_t *item1, list_item_t *item2, slist_t *list){
item1->next = item2->next;
item2->next = item1;
item2->prev = item1->prev;
item1->prev = item2;
if(item1 == list->head){
list->head = item2;
}
if(item2 == list->tail){
list->tail = item1;
}
return item2;
}
I want to write a copy_list function that creates a linked list(the function result) with new nodes that contain the same data as the linked list referenced by the single argument of copy_list.But my copy_list function doesn't work.It goes into infinite loop,While loop doesn't quit.
My structures
typedef struct name_node_s {
char name[11];
struct name_node_s *restp;
}name_node_t;
typedef struct {
name_node_t *headp;
int size;
}name_list_t;
My copy_list function:
name_node_t *copy_list(name_node_t *head){
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t *tail = NULL;
while (current != NULL){
if (newList == NULL) {
newList = malloc(sizeof(name_node_t));
strcpy(newList->name, current->name);
newList->restp = NULL;
tail = newList;
}
else {
tail->restp = malloc(sizeof(name_node_t));
tail = tail->restp;
strcpy(tail->name, current->name);
tail->restp = NULL;
}
current = current->restp;
}
return(newList);
}
Rest of code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct name_node_s {
char name[11];
struct name_node_s *restp;
}name_node_t;
typedef struct {
name_node_t *headp;
int size;
}name_list_t;
name_node_t* presidents(void);
void insertAfter(name_node_t* mynode,name_node_t* newNode);
//void delete_last(name_node_t** headRef);
//void ListDelete(name_list_t* listP, char pname[]);
void lastDelete(name_list_t* listP);
void place_first(name_node_t **headRef, char pname[]);
name_node_t *copy_list(name_node_t *head);
int main(void)
{
name_list_t list;
name_list_t list_two;
//name_node_t *np, *qp;
list.headp = presidents();
name_node_t *new_node;
new_node = malloc(sizeof(name_node_t));
strcpy(new_node->name, "Eisenhower");
insertAfter(list.headp->restp, new_node);
lastDelete(&list);
place_first(&list.headp, "Mustafa");
printf("%s %s %s %s", list.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);
list_two.headp = copy_list(list.headp);
printf("%s %s %s %s", list_two.headp->name, list.headp->restp->name, list.headp->restp->restp->name, list.headp->restp->restp->restp->name);
return(0);
}
name_node_t* presidents(void)
{
name_node_t* head = NULL;
name_node_t* second = NULL;
name_node_t* third = NULL;
head = malloc(sizeof(name_node_t));
second = malloc(sizeof(name_node_t));
third = malloc (sizeof(name_node_t));
strcpy(head->name, "Washington");
head->restp = second;
strcpy(second->name, "Roosevelt");
second->restp = third;
strcpy(third->name, "Kennedy");
third->restp = NULL;
return(head);
}
void insertAfter(name_node_t* mynode,name_node_t* newNode)
{
newNode->restp = mynode->restp;
mynode->restp = newNode;
}
void ListDelete(name_list_t* listP, char pname[]){
name_node_t *to_freep, *cur_nodep;
if(strcmp(listP->headp->name, pname)){
to_freep = listP->headp;
listP->headp = to_freep->restp;
--(listP->size);
}
else {
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL && !strcmp(cur_nodep->restp->name, pname);
cur_nodep = cur_nodep->restp) {
if( cur_nodep->restp != NULL && strcmp(cur_nodep->restp->name, pname)) {
to_freep = cur_nodep->restp;
cur_nodep->restp = to_freep->restp;
free(to_freep);
--(listP->size);
}
}
}
}
void lastDelete(name_list_t* listP){
name_node_t *to_freep, *cur_nodep;
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
to_freep = cur_nodep;
cur_nodep->restp = to_freep->restp;
free(to_freep);
--(listP->size);
}
void place_first(name_node_t **headRef, char pname[]) {
name_node_t *newNode = malloc(sizeof(name_node_t));
strcpy(newNode->name, pname);
newNode->restp = *headRef;
*headRef = newNode;
}
/*name_node_t *copy_list(name_node_t *head) {
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t **lastPtr;
lastPtr = &newList;
while (current != NULL) {
printf("**");
place_first(lastPtr, current->name);
lastPtr = &((*lastPtr)->restp);
current = current->restp;
}
return(newList);
}*/
/*name_node_t *copy_list(name_node_t *head) {
if (head == NULL)
return NULL;
else {
name_node_t *newList = malloc(sizeof(name_list_t));
strcpy(newList->name, head->name);
newList->restp = copy_list(head->restp);
return(newList);
}
}*/
/name_node_t *copy_list(name_node_t *head){
name_node_t *current = head;
name_node_t *newList = NULL;
name_node_t *tail = NULL;
while (current != NULL){
if (newList == NULL) {
newList = malloc(sizeof(name_node_t));
strcpy(newList->name, current->name);
newList->restp = NULL;
tail = newList;
}
else {
tail->restp = malloc(sizeof(name_node_t));
tail = tail->restp;
strcpy(tail->name, current->name);
tail->restp = NULL;
}
current = current->restp;
}
return(newList);
}
In lastDelete(), this loop:
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
... stops at the last node in the list. Afterwards you never set restp to NULL in the second-to-last element. You only work on the last one as to_freep and cur_nodep point to the same element.
This may be easier to do recursively, since singly-linked lists are recursive structures:
A copy of NULL is just NULL.
A copy of a name_node_t is a freshly malloc'd name_node_t with the same name as the original and a copy of the original's restp as its restp.
It's been a long time since I wrote C++. Still:
Doesn't look like there's anything in copy_list that should make it go into an infinite loop.
The logic has:
while (current!=null) current = current->next;
Perhaps copy_list is being passed in a bad list? (i.e A list where the last element does not have restp == null).
In main you are calling:
insertAfter(....);
lastDelete(....);
...
copy_list(....);
So the problem could be in insertAfter or lastDelete ... or ...
Check lastDelete:
name_node_t *to_freep, *cur_nodep;
for (cur_nodep = listP->headp;
cur_nodep->restp != NULL;
cur_nodep = cur_nodep->restp) {}
to_freep = cur_nodep;
cur_nodep->restp = to_freep->restp;
free(to_freep); //what if listP->headp was null? i.e. list had size 0?
--(listP->size);
Plenty of issues
What if you're passed a list with 0 elements?
What if you're passed a list with 1 element?
In any case after you free "to_freep", the node prior to "to_freep" does not have it's restp set to null. So the second last node, now points to a deleted node! This means the list never terminates.
A better lastDelete: (just an algo, can't remember the syntax anymore...)
if (head == null) return; //do nothing
if (head->next == null)
{
listP->head = null;
listP->size = 0;
return;
}
node* prev = head;
head = head->next;
while (head->next != null)
{
prev = head;
head = head->next;
}
//now prev points to a 2nd last node
//head points to last node
free(head);
prev->restp = null;