I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.
Related
This question already has answers here:
Linked lists - single or double pointer to the head
(3 answers)
What is the reason for using a double pointer when adding a node in a linked list?
(15 answers)
Closed 10 months ago.
#include<stdio.h>
#include<stdlib.h>
void insert_front(struct node* head, int block_number);
void insert_rear(struct node* head, int block_number);
void print_list(struct node* head);
struct node {
int block_number;
struct node* next;
};
int main(void)
{
struct node* list = NULL;
insert_front(list, 10);
insert_rear(list, 20);
insert_front(list, 30);
insert_rear(list, 40);
print_list(list);
return 0;
}
void insert_front(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
void insert_rear(struct node* head, int block_number)
{
struct node* p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL) {
head = p;
}
else {
struct node* q = head;
while (q->next != NULL) {
q = q->next;
}
q->next = p;
}
}
void print_list(struct node* head)
{
struct node* p = head;
while (p != NULL) {
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
When I ran it, there was no result at all.
Now, in the insert_front function p->block_number = block_number, a message appears saying that the NULL pointer 'p' is being dereferenced... (The same thing appears in the insert_rear function.)
Could it be that I am declaring the pointer wrong?
Both insert_front and insert_rear need to convey possibly head modification back to the caller, and the caller needs to reap that information. Both should be declared to return struct node *, do so, and the code in main react accordingly. E.g.:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <stdlib.h>
struct node * insert_front(struct node *head, int block_number);
struct node * insert_rear(struct node *head, int block_number);
void print_list(struct node *head);
struct node
{
int block_number;
struct node *next;
};
int main(void)
{
struct node *list = NULL;
list = insert_front(list, 10);
list = insert_rear(list, 20);
list = insert_front(list, 30);
list = insert_rear(list, 40);
print_list(list);
return 0;
}
struct node *insert_front(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = head;
head = p;
return head;
}
struct node *insert_rear(struct node *head, int block_number)
{
struct node *p = malloc(sizeof(struct node));
p->block_number = block_number;
p->next = NULL;
if (head == NULL)
{
head = p;
}
else
{
struct node *q = head;
while (q->next != NULL)
{
q = q->next;
}
q->next = p;
}
return head;
}
void print_list(struct node *head)
{
struct node *p = head;
while (p != NULL)
{
printf("--> %d ", p->block_number);
p = p->next;
}
printf("\n");
}
Output
--> 30 --> 10 --> 20 --> 40
I leave the memory leaks for you to resolve.
In C all variables are passed by value – if you pass a pointer, then it is copied, too (not the pointed to object, of course...), and function parameters, apart from being initialised from outside, are nothing more than local variables. Thus via head = p; you just assign the local copy of the outside pointer, not the latter itself!
To fix that you have two options:
Return the new head and make the user responsible for re-assigning the returned value to his own head pointer.
Accept the head as pointer to pointer.
With second approach a user cannot forget to re-assign the (potentially) new head, so that's what I'd go with:
void insert_whichEver(node** head, int block_number)
{
// use `*head` where you had `head` before...
}
void demo()
{
node* head = NULL;
insert_front(&head, 1012);
}
And in insert_front drop return head;, a function with void cannot return anything concrete and does not require a return at all (but bare return; can be used to exit a function prematurely).
I am trying to sort a doubly linked list in ascending order. I've gone trough the code again and again, and I can't find any logical flaws with it, so I assume the problem is elsewhere. When I try to print the sorted list, the console returns 0 without printing anything (the print function is not to blame, since it has already been tested)
Here is the code I am currrently running:
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
//receives the original head pointer
//returns sorted list's head pointer
Node** SortDate(struct Node** head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )//iterates over the entire list
{
//if the data value of the next node is bigger
if ( i->payload.ano > i->next->payload.ano )
{
//swaps the data value between i and i->next
//SwapNodes was tested and it is working
SwapNodes(i, i->next);
//the current value of i->next (former value of i)
//is compared to all the previous values
//and keeps swapping until a smaller value is found
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
return head;
}//sort
I know there probably are easier ways to sort doubly linked list, but I'm trying to figure out why this one doesn't work.
Thank you in advance!
EDIT:
showing all the involved functions:
#include <stdio.h>
#include <stdlib.h>
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
Node * CreateCitiesList();
Node * CreateCountriesList();
Node * Intervalos(struct Node*, int[]);
void PrintBack(struct Node*);
struct Node* CreateNode (dados_temp x)
{
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
NewNode->payload = x;
NewNode->next = NULL;
NewNode->prev = NULL;
return NewNode;
}
}
void Print (struct Node* head)
{
struct Node* temp = head;
while ( temp != NULL)
{
printf("%d-%d-%d \n", temp->payload.ano, temp->payload.mes,
temp>payload.dia);
fflush(stdout);
temp = temp->next;
}
printf("\n");
}
Node* SortDate (struct Node*);
void SwapNodes (struct Node*, struct Node*);
int main(int argc, char* argv[])
{
CreateCountriesList();
}
Node* CreateCountriesList()
{
char linha[150] = {NULL};
char cabecalho[100] = {NULL};
int i = 0;
dados_temp New_Entry;
dados_temp tail;
int *ptr_head_co;
struct Node* head_countries = NULL;
struct Node* Node = NULL;
FILE *inputf;
inputf = fopen("tempcountries_all.csv", "r");
if (inputf == NULL)
{
printf("Nao da pa abrir o fitchas boi");
exit(EXIT_FAILURE);
}
//gets rid of the first line
fgets(cabecalho, 100, inputf);
for (i = 0; i < 577462 ; i++)
{
fgets(linha, 150, inputf);
//scans the date(amongst other things) from file (yyyy-mm-dd)
sscanf(linha, "%d-%d-%d,%f,%f,%[^,]s", &New_Entry.ano,
&New_Entry.mes,&New_Entry.dia, &New_Entry.temp, &New_Entry.incerteza,
&New_Entry.pais);
if (head_countries == NULL)
{
head_countries = CreateNode(New_Entry);
Node = CreateNode(New_Entry);
}
else
{
head_countries = InsertHead(head_countries, New_Entry);
}
}
fclose(inputf);
head_countries = RemoveNodes(Node);
SortDate(head_countries);
Print(head_countries);
return head_countries;
}
Node* SortDate(struct Node* head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )
{
if ( i->payload.ano > i->next->payload.ano )
{
SwapNodes(i, i->next);
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
}//sort
void SwapNodes(struct Node* node1, struct Node* node2)
{
dados_temp temp = node1->payload;
node1->payload = node2->payload;
node2->payload = temp;
}
My professor send me a library to insert,delete and search elements in a linked list:
#include <stdlib.h>
struct NODE
{
char AM[12];
char name[40];
int semester;
struct NODE *head;
struct NODE *next;
struct NODE *prev;
};
void init(struct NODE **head)
{
*head=NULL;
}
struct NODE *Search (struct NODE *head,char CODE[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->AM<CODE)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->AM==CODE)
return tmp;
return NULL;
}
struct NODE *Search2 (struct NODE *head,char name[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->name<name)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->name==name)
return tmp;
return NULL;
}
int Insert (struct NODE **H,struct NODE P)
{
struct NODE *cur,*prev;
cur=Search(*H,P.AM,&prev);
if (cur)
return 0;
cur=(struct NODE *)malloc(sizeof P);
*cur=P;
if (prev==NULL)
{
cur->next=*H;
*H=cur;
}
else
{
cur -> next = prev -> next;
prev -> next = cur;
}
return 1;
}
int Delete (struct NODE **H,char AM[])
{
struct NODE *cur,*prev,*next;
cur=Search(*H,AM,&prev);
if (!cur)
return 0;
if (prev==NULL)
cur=next;
else
prev->next=cur->next;
free(cur);
return 1;
}
void traverse (struct NODE *head)
{
struct NODE *cur;
cur=head;
while (cur)
{
printf ("%p\n",cur);
cur=cur->next;
}
}
Now here is a piece of code from the source file that i created in an attempt to insert an element in the linked list:
case 1:printf ("Input AM,name and semester of student: ");
tmp=(struct NODE *)malloc(sizeof(struct NODE));
if (tmp==NULL)
exit(1);
scanf("%s %s %d",tmp->AM,tmp->name,&tmp->semester);
_flag=Insert(&head,*tmp);
if(_flag)
printf ("Student inserted succesfully!\n");
free(tmp);
break;
When i insert the element i get the "Student inserted succesfully" message,but when i call the search function to find that element,it returns NULL (meaning that the element is not in the list).How should i call the Insert function from the header file? (I assume the problem must be in the Insert function).Also in main() i have declared the following two:
struct NODE *head;
struct NODE *tmp;
Should i change something regarding those two?
I think your problem is in the Search() and Search2() functions, where you've got things like this:
while (tmp!=NULL && tmp->AM<CODE)
and
if (tmp->AM==CODE)
return tmp;
You're comparing the pointers, rather than the contents of the strings. If you want to compare the strings, or find which is first alphabetically, use strcmp().
while (tmp!=NULL && strcmp(tmp->AM, CODE) < 0)
and
if (!strcmp(tmp->AM, CODE))
return tmp;
The same goes for the comparison between tmp->name and name in Search2().
Okay so I've been doing a program which would read elements of a txt file using scanf (cmd input redirection). A new node must be created for every entry in the file and add it at the end of the list. Here's my code so far:
struct Elem{
int Atnum;
char Na[31];
char Sym[4];
};
struct nodeTag {
struct Elem entry;
struct nodeTag *pNext; // pointer to the next node
};
typedef struct nodeTag Node;
The function that would initialize it is this:
Node *
InitializeList(Node *pFirst, int n)
{
int i;
Node *head, *temp = 0;
pFirst = 0;
for (i=0; i<n; i++){
head = (Node *)malloc(sizeof(Node));
scanf("%d", &head->entry.AtNum);
scanf("%s", head->entry.Na);
scanf("%s", head->entry.Sym);
if (pFirst != 0)
{
temp->pNext = head;
temp = head;
}
else
{
pFirst = temp = head;
}
fflush(stdin);
temp->pNext = 0;
}
return pFirst;
}
and lastly, print it
void
Print( Node *pFirst )
{
Node *temp;
temp = pFirst;
printf("\n status of the linked list is\n");
while (temp != 0)
{
printf("%d %s %s", temp->entry.AtNum, temp->entry.Na, temp->entry.Sym);
temp = temp -> pNext;
}
}
Now, I can't get the program to run properly. No run-time errors though but the output seems to be garbage. I've been working for hours for this and I cant' get my head around it. Thank you for your help!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Elem
{
int AtNum;
char Na[31];
char Sym[4];
};
struct nodeTag
{
/* entry must be a pointer in order to not lose the values
and/or encounter memory conflicting errors
*/
struct Elem *entry;
struct nodeTag *pNext;
};
typedef struct nodeTag Node;
// insert node at the first location
Node *insertFirst(Node *head, struct Elem *data)
{
Node *node = (Node *) malloc(sizeof(Node));
// fill in data
node->entry = data;
/* point it to old first node
in simple words: "put this node before the head"
*/
node->pNext = head;
// point first to new first node
head = node;
return head;
}
Node *InitializeList(int n)
{
int i;
Node *head = NULL;
struct Elem *data;
for (i = 0; i < n; i++)
{
// allocate memory for the struct Elem of each node
data = (struct Elem*) malloc(sizeof(struct Elem));
scanf("%d", &data->AtNum);
scanf("%s", data->Na);
scanf("%s", data->Sym);
head = insertFirst(head, data);
}
return head;
}
//display the list
void printList(Node *head)
{
Node *ptr = head;
printf("\nStatus of the linked list is:\n");
//start from the beginning
while(ptr != NULL)
{
printf("%d %s %s", ptr->entry->AtNum, ptr->entry->Na, ptr->entry->Sym);
printf("\n");
ptr = ptr->pNext;
}
}
int main(int argc, char *argv[])
{
Node *head;
head = InitializeList(3);
printList(head);
return 0;
}
I hope I didn't come too late! If not, please check this answer as the solution, thanks! :-)
I was having some confusion between ListNode and LinkedList. Basically my question was divided into 2 parts. For first part, I was supposed to do with ListNode. The function prototype as such:
int removeNode(ListNode **ptrHead, int index);
All function were working fine for the ListNode part. Then as for the second part, I was supposed to change the function above to this:
int removeNode(LinkedList *11, int index);
My code for part 1 which is working fine look like this:
int removeNode(ListNode **ptrHead, int index) {
ListNode *pre, *cur;
if (index == -1)
return 1;
else if (findNode(*ptrHead, index) != NULL) {
pre = findNode(*ptrHead, index - 1);
cur = pre->next;
pre->next = cur->next;
return 0;
}
else
return 1;
}
ListNode *findNode(ListNode *head, int index) {
ListNode *cur = head;
if (head == NULL || index < 0)
return NULL;
while (index > 0) {
cur = cur->next;
if (cur == NULL) return NULL;
index--;
}
return cur;
}
And here is my entire code for the part 2 which is not working:
#include "stdafx.h"
#include <stdlib.h>
typedef struct _listnode {
int num;
struct _listnode *next;
}ListNode;
typedef struct _linkedlist {
ListNode *head;
int size;
}LinkedList;
void printNode2(ListNode *head);
int removeNode2(LinkedList *ll, int index);
int main()
{
int value, index;
ListNode *head = NULL, *newNode = NULL;
LinkedList *ptr_ll = NULL;
printf("Enter value, -1 to quit: ");
scanf("%d", &value);
while (value != -1) {
if (head == NULL) {
head = malloc(sizeof(ListNode));
newNode = head;
}
else {
newNode->next = malloc(sizeof(ListNode));
newNode = newNode->next;
}
newNode->num = value;
newNode->next = NULL;
scanf("%d", &value);
}
printNode2(head);
printf("\nEnter index to remove: ");
scanf("%d", &index);
removeNode2(ptr_ll, index);
printNode2(head);
return 0;
}
void printNode2(ListNode *head) {
printf("Current list: ");
while (head != NULL) {
printf("%d ", head->num);
head = head->next;
}
}
int removeNode2(LinkedList *ll, int index) {
ListNode *head = ll->head;
if (head == index)
{
if (head->next == NULL)
{
printf("There is only one node. The list can't be made empty ");
return 1;
}
/* Copy the data of next node to head */
head->num = head->next->num;
// store address of next node
index = head->next;
// Remove the link of next node
head->next = head->next->next;
return 0;
}
// When not first node, follow the normal deletion process
// find the previous node
ListNode *prev = head;
while (prev->next != NULL && prev->next != index)
prev = prev->next;
// Check if node really exists in Linked List
if (prev->next == NULL)
{
printf("\n Given node is not present in Linked List");
return 1;
}
// Remove node from Linked List
prev->next = prev->next->next;
return 0;
}
When I try to run the part 2, the cmd just not responding and after a while, it just closed by itself and I have no idea which part went wrong. I was thinking am I in the correct track or the entire LinkedList part just wrong?
When I tried to run in debug mode, this error message popped up:
Exception thrown at 0x01201FD1 in tut.exe: 0xC0000005: Access violation reading location 0x00000000.
If there is a handler for this exception, the program may be safely continued.
Thanks in advance.
You say that you got the linked list to work wihen the list is defined via the head pointer only. In this set-up, you have to pass a pointer to the head pointer when the list may be updated, and just the head pointer when you only inspect the list without modifying, for example:
int removeNode(ListNode **ptrHead, int index);
ListNode *findNode(ListNode *head, int index);
Here, the head pointer is the handle for the list that is visible to the client code.
The approach with the list struct defines a new interface for the linked list. While the head node is enough, it might be desirable to keep track of the tail as well for easy appending or of the number of nodes. This data can be bundles in the linked list struct.
What that means is that the handling of the nodes is left to the list and the client code uses only the linked list struct, for example:
typedef struct ListNode ListNode;
typedef struct LinkedList LinkedList;
struct ListNode {
int num;
ListNode *next;
};
struct LinkedList {
ListNode *head;
ListNode *tail;
int size;
};
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
void ll_append(LinkedList *ll, int num);
void ll_remove_head(LinkedList *ll);
int main()
{
LinkedList ll = {NULL};
ll_append(&ll, 2);
ll_append(&ll, 5);
ll_append(&ll, 8);
ll_print(&ll);
ll_prepend(&ll, 1);
ll_prepend(&ll, 0);
ll_print(&ll);
ll_remove_head(&ll);
ll_print(&ll);
while (ll.head) ll_remove_head(&ll);
return 0;
}
There's also one difference: In the head-node set-up, the head node might be null. Here, the list cannot be null, it must exist. (Its head and tail members can be null, though.) Here the list is allocated on the stack, its address &ll must be passed to the functions.
In the linked list set-up, the distinction between modifying and read-only access is done via the const keyword:
void ll_print(const LinkedList *ll);
void ll_prepend(LinkedList *ll, int num);
In your example, you take a mixed approach with two independent structures, a head node and a list. That can't work, one single list is described by one struct, pick one.
The advantage to the linked list structure approach is that all required data like head, tail and size are always passed together to a function. You can also hide the implementation from the user by not disclosing the struct members, so that theb user can only work on pointers to that struct.
Finally, here's an example implementation of the above interface for you to play with:
void ll_print(const LinkedList *ll)
{
ListNode *node = ll->head;
while (node != NULL) {
printf("%d ", node->num);
node = node->next;
}
putchar('\n');
}
void ll_prepend(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = ll->head;
nnew->num = num;
ll->head = nnew;
if (ll->tail == NULL) ll->tail = ll->head;
ll->size++;
}
void ll_append(LinkedList *ll, int num)
{
ListNode *nnew = malloc(sizeof *nnew);
nnew->next = NULL;
nnew->num = num;
if (ll->tail == NULL) {
ll->tail = ll->head = nnew;
} else {
ll->tail->next = nnew;
ll->tail = nnew;
}
ll->size++;
}
void ll_remove_head(LinkedList *ll)
{
if (ll->head) {
ListNode *ndel = ll->head;
ll->head = ll->head->next;
ll->size--;
free(ndel);
}
}