Traverse backward DLL after deleting first node - c

I have doubly linked list set up using an insertion method which works.
Using this struct:
struct NODE
{
struct NODE *fwd;
struct NODE *bwd;
int value;
};
typedef struct NODE Node;
And this initialization:
void initializeList(Node *rt)
{
rt->fwd = NULL;
rt->bwd = NULL;
rt->value = 0;
}
My main function is:
main()
{
Node root;
int j;
initializeList(&root);
for (j = 0; j < 15; j++)
insertFirst(&root, j);
printf("The list traversed forward \n");
traverseForward(root);
printf("\n");
printf("The list traversed backward \n");
traverseBackward(root);
printf("\n");
printf("After first deletion traverse forward\n");
deleteFirst(&root);
traverseForward(root);
printf("\n");
printf("After first deletion traverse backwards\n");
printf("\n");
traverseBackward(root);
}
My deletefirst function is:
void deleteFirst(Node *rt)
{
Node *newnode = rt;
Node *tmp = NULL;
if (newnode != NULL)
{
if (newnode->fwd != NULL)
{
newnode = newnode->fwd;
tmp = newnode->bwd;
*rt = *newnode;
}
else
tmp = newnode;
}
free(tmp);
}
Insert function:
int insertFirst(Node *rt, int val)
{
Node *node = (Node *)malloc(sizeof(Node));
if (node == NULL) return 0;
node->value = val;
/* For a previously empty list */
if (rt->fwd == NULL)
{
rt->fwd = node;
rt->bwd = node;
node->fwd = NULL;
node->bwd = NULL;
}
/* For a list with at least one node */
else
{
/* previous first node now new node's successor */
rt->fwd->bwd = node;
node->fwd = rt->fwd;
/* no predecessor to the new first node */
node->bwd = NULL;
/* root points to this new first */
rt->fwd = node;
}
return 1;
}
Traverse functions:
void traverseForward(Node root)
{
Node *q = root.fwd;
while (q)
{
printf("%d ", q->value);
q = q->fwd;
}
}
void traverseBackward(Node root)
{
Node *q = root.bwd;
while (q)
{
printf("%d ", q->value);
q = q->bwd;
}
}
The system prints out the list traversed forward
14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
The system prints out the list traversed backward
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
After first deletion forward traversal
13 12 11 10 9 8 7 6 5 4 3 2 1 0
After first deletion backward traversal
(Nothing is printed)
I cant figure out how to adjust the pointers to get it to work.

I believe the problem is because the odd way you are storing the head and tail pointers to the start and end of the list in a root node and then mixing that interchangeably with the actual nodes of the list. This confusion could be eliminated if you just have simple Node *head and Node *tail pointers, but that is only a suggestion.
In your delete function, you set the root node to effectively rt->fwd, which is fine for forwards traversal as rt->fwd->fwd is what is desired, but you forget to consider the value of rt->fwd->bwd which is always pointing at NULL for the first item in the list (as there is nothing technically before this node), not the actual tail of the list which is the desired functionality by that logic.
This obviously causes a problem when you try to use it to iterate backwards as it thinks the list is empty. You should change your deletion code to something like this:
void deleteFirst(Node *rt)
{
if (rt == NULL)
{
return; /* Return if an invalid root was passed in */
}
if (rt->fwd == NULL) {
return; /* Return if the list is already empty */
}
Node *tmpfwd = rt->fwd; /* Store the current "head" */
rt->fwd = rt->fwd->fwd; /* Set the root's head to the current head's next node */
rt->fwd->bwd = NULL; /* Set the new head's previous node to NULL as it is the start of the list */
free(tmpfwd); /* Delete the old "head" */
}
There are a lot of other problems here regarding edge cases and things the comments have mentioned (just the overall design makes this very problematic) but I think this is the problem you are having currently.

Related

LinkedList Adding Node compared by size with C

Today, I got a new homework from my teacher.
He told me that this homework might be a sample for final exam.
I tried it for about 2 ~ 3 hours, but I can't get it.
He gave me a simple LinkedList Code. Below in bold is what he wants.
Would you give me some hint about comparing size of Nodes?
Adding Nodes Compared with pre Node and After Node.
2 --> 5 --> 10 --> 20
When I InsertMiddleNode( 7 ), Automatically compare input number(7) with ListNode And locate the right Place
My Goal : 2 --> 5 --> 7(which is my input) --> 10 --> 20
Teacher's code is below:
void insertMiddleNode(linkedList_h* L, listNode* pre, int x) {
listNode* newNode;
newNode = (listNode*)malloc(sizeof(listNode));
newNode->data = x;
if (L == NULL) { // Empty
newNode->link = NULL; // connect
L->head = newNode;
}
else if (pre == NULL) { //
L->head = newNode; // Insert Node at First
}
else {
newNode->link = pre->link; // after pre node
pre->link = newNode;
}
}
Or could it be possible for implementing the same function in main code?
int main() {
linkedList_h* L;
listNode* p;
L = createLinkedList_h();
insertLastNode(L, 1);
insertLastNode(L, 5);
insertLastNode(L. 10);
insertLastNode(L, 20); // 1 - 5 - 10 - 20
insertMiddleNode(L, p, 7) // using p = scanf("%d") with If ( p < pre Node )
printList(L) // 2 - 5 - 7 - 10 - 20
}
void MiddleNode(linkedList_h* L, int x) {
if (L == null)
return
//setp 1: find the previous node
listNode* prev = null;
for (listNode* node = L->head; node && node->data < x; node = node->link)
prev = node;
//step2: be sure prev is not null
if (prev == null)
return;
//or call inserFirstNode(L, x) and return
//step 3: call your teacher's function
insertMiddleNode(L, prev, x);
return;
}
return if L doesn't exist, or you'll crash
the first step is quite simple, loop through the list to find the previous element
but you may end up with null as prev node (either cause the list is empty or x is the smallest), in both case you need to return (or you'll break the list).
Then just call your teacher's function

Taking values from stdin and storing those in linked list nodes

Yesterday after I did a stupid approach, I think I am on a good way right now. The thing I wanna program is that I am getting n values from the user and I am trying to store every value into a linked list node which has to be sorted after every input.
So it means:
Input:
5 1 9
Output:
1 5 9
Input:
2 3
Output:
1 2 3 5 9
My code so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
int val;
struct node* next;
} node;
void printList(node* n) {
while (n != NULL) {
printf("%d ", n->val);
n = n->next;
}
}
void push(node * head, int val) {
node * current = head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
current->next = malloc(sizeof(node));
current->next->val = val;
current->next->next = NULL;
}
int main() {
char input[20];
char* ptr;
node* head = NULL;
head = (node*) malloc(sizeof(node));
do {
printf("Eingabe:");
fgets(input,20,stdin);
ptr = strtok(input," ");
while(ptr!=NULL){
int val = atoi(ptr);
push(head,val);
ptr = strtok(NULL, " ");
}
printList(head);
}
while(*input != '0');
return 0;
}
Edited my code, node creation is working , but when I input 5 1 9 , it outputs 0 5 1 9 where is that 0 coming from?
The 0 is the value of your head.
When you create the first node you add it as the next of the head, this means that by having as input 5 1 9 your linked list will be:
head -> 5 -> 1 -> 9
When you print you don't just print the values of the nodes you have created but also the value of the head, since the value was never initialized and in the struct it's an int your compiler intializes it to 0 automatically (this depends on the compiler implementation so it's always better to initialize it).
If you don't want that 0 in the front you have a couple of options:
assign to head->value the first number that you input
call the printList as printList(head->node)
change your linked list implementation to not have the head hold a value
change printList to:
void printList(node* n) {
n = n->next;
while (n != NULL) {
printf("%d ", n->val);
n = n->next;
}
}
The correct approach could be (pseudo-code):
[START]
Read new line from the STDIN;
While there are new values:
Read new value;
Add it on new node (easier adding on top of the list);
Sort the list;
Print the list;
Loop to [START]
In your code you are missing the "sort the list" phase.
Easier if you add a swap function and try one of sorting algorithm on your choice

Designing a Queue in C. Segfault when adding element to queue

I am having a problem with a queue program I am writing in C. This is a circular queue, so the last item must also point to the first item. The problem exists within the addQueue function. First I check whether the head pointer is set to NULL, if it is then I add the first item to the queue. However, head is not equal to NULL, then I add the item to the end of the queue. I create an iterate pointer to iterate until it finds the end when:
iterate->next == *head;
The problem I am having is that when I create iterate and set it to *head, it is not operating as it should. Here is my code and the output I have received, I added some prints in the code to show the problem I am having.
#include <stdlib.h>
#include <stdio.h>
//define the Q element struct
typedef struct _item{
struct _item* next;
struct _item* prev;
int data;
} item;
item * newItem(){
item * node = malloc(sizeof(item));
return node;
}
void initQueue(item ** head){
*head = NULL; //Empty queue means head points to NULL
}
void addQueue(item ** head, item item_p){
//create new item
item * newIt = newItem();
newIt = &item_p;
printf("NewItem: %d\n\n", newIt->data);
//if *head is NULL, make it point to item
if(*head == NULL)
{
*head = newIt; //set head to address of item
newIt->next = *head;
printf("Again: %p\n\n", *head);
}
//else the list is not empty, add item to end of list
else
{
item * iterate = NULL;
iterate = *head;
printf("it: %p head: %p\n\n", iterate, *head);
/*while (iterate->next != *head)
{
iterate = iterate->next;
}
iterate->next = newIt;
newIt->next = *head;*/
}
}
Here is the .c file I wrote to test the functions:
#include "q.h"
#include <stdio.h>
int main ()
{
item i1;
i1.data = 1;
item i2;
i2.data = 2;
item i3;
i3.data = 3;
item * headTemp;
initQueue(&headTemp);
addQueue(&headTemp, i1);
printf("HEAD: %d\n", headTemp->data);
addQueue(&headTemp, i2);
printf("HEAD: %d\n", headTemp->data);
addQueue(&headTemp, i3);
return 0;
}
And the output is:
NewItem: 1
Again: 0x7fff2252eb10
HEAD: 1
NewItem: 2
it: 0x7fff2252eb10 head: 0x7fff2252eb10
HEAD: 2
NewItem: 3
it: 0x7fff2252eb10 head: 0x7fff2252eb10
Segmentation fault
I created three items to insert into the queue. The first is placed in without issue. However I have problems when I insert a second item. The headTemp->data should remain the same no matter what I place into the queue, however it goes from 1 to 2 to 3, which is the data for all items I created. I'm not really sure what the problem is, and the answer may be staring me in the face. But I would really appreciate some help with this.
Cheers!
Thanks for posting paste-able code. Right out of the gate, this is wrong:
item * newIt = newItem();
newIt = &item_p;
this is an immediate memory leak. Worse the address your replacing it with is a by-value automatic variable. Therefore the address is going to be invalid to even evaluate, much less dereference, as soon as this function is finished.
Next, you need to prime your nodes with valid state for all member variables. How you do this is up to you, but the simplest way is in the node-creation code. To really do this properly, your node creation code should be a "factory" function. I.e. it should take as parameters what is needed to initialize the node. So do this first:
item* newItem( int data )
{
item * node = malloc(sizeof(item));
if (item == NULL)
{
perror("failed to allocate node.");
exit(EXIT_FAILURE);
}
node->data = data;
node->next = node->prev = NULL;
return node;
}
Once you have that solid, you can modify your addQueue to do this:
void addQueue(item** head, int data)
{
item *prev = NULL;
while (*head)
{
prev = *head;
head = &prev->next;
}
*head = newItem(data);
(*head)->prev = prev;
}
This code is still a ways off from being a deque. You need two pointers to do that, and the best place to keep them is in a separate struct, along with a count to make size-inquiries O(1). Properly done, insertion is O(1) in a full deque, but you'll get there eventually.
Anyway, an updated main appears below for testing everything made it in. Eventually you want a pop-functoin, etc.
int main()
{
item *q = NULL;
for (int i=1; i<=20; ++i)
addQueue(&q, i);
item *p = q;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return 0;
}
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Your addQueue() function is not appropriate.
void addQueue(item ** head, item item_p){
28 //create new item
29 item * newIt = newItem();
30 newIt = &item_p;
31 printf("NewItem: %d\n\n", newIt->data);
32
33 //if *head is NULL, make it point to item
34 if(*head == NULL)
35 {
36 *head = newIt; //set head to address of item
37 newIt->next = *head;
38 printf("Again: %p\n\n", *head);
39 }
In this you do newItem() to get newly allocated node, but you again re-assign it to &itemp_p on line 30. This is not good, as you are not using allocated memory, but items variables i1, i2, i3 declared in main().
Also, in newItem() set next and prev to NULL
17 item * newItem(){
18
19 item * node = malloc(sizeof(item));
if(node) { //You can use calloc too.
node->next = NULL;
node->prev = NULL;
}
20 return node;
21 }

Remove an element from linked list at a given position

I have a simple question about removing an element from a linked list. The only difference between what I am trying to accomplish and what I have seen in code online is that I am trying to remove an element, given a position, rather than given the actual element that needs to be removed.
Any help is appreciated.
You can do that, Here is the sample program which can delete any node based on the index you are supplying as an argumenT.
start -> Pointing to the first node
traverse ->pointing to the node which has to be deleted
traverseNext->pointing to the previous of node which has to be deleted.
And the code looks like below.
#include <iostream>
struct myList
{
int data;
struct myList *next;
};
struct myList *start=NULL;
//this method removes a node from the position index
void remove(int index)
{
myList *traverse = start;
myList *traverseNext = NULL;
int i = 1;
while(i<(index-1))
{
traverse = traverse->next;
i++;
}
traverseNext = traverse;
traverse = traverse->next;
if(traverse->next == NULL)
{
delete traverse;
traverseNext->next = NULL;
traverse = NULL;
return;
}
else
{
traverseNext->next = traverse->next;
delete traverse;
traverse = NULL;
return;
}
}
int main(void)
{
myList *node1;
myList *node2;
myList *node3;
node1 = new myList;
node2 = new myList; //Created 3 nodes of type myList
node3 = new myList;
node1->data = 10;
node1->next = node2;
node2->data = 20;
node2->next = node3;
node3->data = 30;
node3->next = NULL;
start = node1; //start is pointing to node1
remove(2); //removing the node 2, so the output will be 10 30
while(start) //iterating through all the nodes from start, since start
{ //is pointing to the first node.
std::cout<<start->data<<" ";
start = start->next;
}
}
Deleting a node in a linked list to which the pointer is given can be done in O(1) time. We don't have to do traversal.
I am assuming that by position you meant the pointer to the node is given:
Lets say node is the element that needs to be removed.
node->data = node->next->data;
Node* temp = node->next;
node->next = node->next->next;
free(temp);
But if the position means the nth element in the list, the only way would be to traverse up to the (n-1)th element and delete the next element by (regular deletion in a linked list):
Node* temp = previous->next;
previous->next = temp->next;
free(temp);
This is all assuming that the linked-list is a pointer based linked-list
This is simple:
1) Locate the Nth item by iterating through the list, additionally using a counter to keep track of which node you're one.
2) Remove that node, as you would any other linked list.
Seek the list until you find the nth element (use a counter), and then update the previous node's next pointer to point to the one after the one you're currently at (effectively removing it). Adjust the previous pointer if you're using them, too.
If you want to remove multiple items you can first iterate over the list and then collect all items that you want to remove to another list. Then simply call 'removeAll' passing in the collected list.
#include <stdio.h>
#include <stdlib.h>
typedef struct element{
int num;
struct element * next;
} element;
void delNth(element **header, int pos){//pos : zero origin
element *prev, *tmp;
int i;
if(header == NULL || *header == NULL || pos < 0) return ;
if(pos == 0){
tmp = (*header)->next;
free(*header);
*header = tmp;
} else {
prev = *header;
tmp = (*header)->next;
for(i=1;i<pos;++i){
prev = tmp;
tmp = tmp->next;
if(tmp == NULL) return ;//or rise error
}
prev->next = tmp->next;
free(tmp);
}
}
void drop(element *header){
if(header){
drop(header->next);
free(header);
}
}
void printList(element *header){
while (header!=NULL){
printf("%d ",header->num);
header=header->next;
}
printf("\n");
}
int main(int argc, char **argv){
int pos = atoi(argv[1]);
element *a;
element *b;
element *c;
a=malloc(sizeof(element));
b=malloc(sizeof(element));
c=malloc(sizeof(element));
a->num=5;
b->num=6;
c->num=7;
a->next=b;
b->next=c;
c->next=NULL;
printList(a);
delNth(&a, pos);
printList(a);
drop(a);
return 0;
}
/* execute result
>a 0
5 6 7
6 7
>a 1
5 6 7
5 7
>a 2
5 6 7
5 6
>a 3
5 6 7
5 6 7
*/

Splitting a linked list

Why are the split lists always empty in this program? (It is derived from the code on the Wikipedia page on Linked Lists.)
/*
Example program from wikipedia linked list article
Modified to find nth node and to split the list
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct ns
{
int data;
struct ns *next; /* pointer to next element in list */
} node;
node *list_add(node **p, int i)
{
node *n = (node *)malloc(sizeof(node));
if (n == NULL)
return NULL;
n->next = *p; //* the previous element (*p) now becomes the "next" element */
*p = n; //* add new empty element to the front (head) of the list */
n->data = i;
return *p;
}
void list_print(node *n)
{
int i=0;
if (n == NULL)
{
printf("list is empty\n");
}
while (n != NULL)
{
printf("Value at node #%d = %d\n", i, n->data);
n = n->next;
i++;
}
}
node *list_nth(node *head, int index) {
node *current = head;
node *temp=NULL;
int count = 0; // the index of the node we're currently looking at
while (current != NULL) {
if (count == index)
temp = current;
count++;
current = current->next;
}
return temp;
}
/*
This function is to split a linked list:
Return a list with nodes starting from index 'int ind' and
step the index by 'int step' until the end of list.
*/
node *list_split(node *head, int ind, int step) {
node *current = head;
node *temp=NULL;
int count = ind; // the index of the node we're currently looking at
temp = list_nth(current, ind);
while (current != NULL) {
count = count+step;
temp->next = list_nth(head, count);
current = current->next;
}
return temp; /* return the final stepped list */
}
int main(void)
{
node *n = NULL, *list1=NULL, *list2=NULL, *list3=NULL, *list4=NULL;
int i;
/* List with 30 nodes */
for(i=0;i<=30;i++){
list_add(&n, i);
}
list_print(n);
/* Get 1th, 5th, 9th, 13th, 18th ... nodes of n etc */
list1 = list_split(n, 1, 4);
list_print(list1);
list2 = list_split(n, 2, 4); /* 2, 6, 10, 14 etc */
list_print(list2);
list3 = list_split(n, 3, 4); /* 3, 7, 11, 15 etc */
list_print(list3);
list3 = list_split(n, 4, 4); /* 4, 8, 12, 16 etc */
list_print(list4);
getch();
return 0;
}
temp = list_nth(current, ind);
while (current != NULL) {
count = count+step;
temp->next = list_nth(head, count);
current = current->next;
}
You are finding the correct item to begin the split at, but look at what happens to temp from then on ... you only ever assign to temp->next.
You need to keep track of both the head of your split list and the tail where you are inserting new items.
The program, actually, has more than one problem.
Indexes are not a native way to address linked list content. Normally, pointers to nodes or iterators (which are disguised pointers to nodes) are used. With indexes, accessing a node has linear complexity (O(n)) instead of constant O(1).
Note that list_nth returns a pointer to a "live" node within a list, not a copy. By assigning to temp->next in list_split, you are rewiring the original list instead of creating a new one (but maybe it's intentional?)
Within list_split, temp is never advanced, so the loop just keeps attaching nodes to the head instead of to the tail.
Due to use of list_nth for finding nodes by iterating through the whole list from the beginning, list_split has quadratic time (O(n**2)) instead of linear time. It's better to rewrite the function to iterate through the list once and copy (or re-attach) required nodes as it passes them, instead of calling list_nth. Or, you can write current = list_nth(current, step).
[EDIT] Forgot to mention. Since you are rewiring the original list, writing list_nth(head, count) is incorrect: it will be travelling the "short-cirquited" list, not the unmodified one.
I also notice that it looks like you are skipping the first record in the list when you are calculating list_nth. Remember is C we normally start counting at zero.
Draw out a Linked List diagram and follow your logic:
[0]->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]->...->[10]->[NULL]
Your description of what list_split is supposed to return is pretty clear, but it's not clear what is supposed to happen, if anything, to the original list. Assuming it's not supposed to change:
node *list_split(node *head, int ind, int step) {
node *current = head;
node *newlist=NULL;
node **end = &newlist;
node *temp = list_nth(current, ind);
while (temp != NULL) {
*end = (node *)malloc(sizeof(node));
if (*end == NULL) return NULL;
(*end)->data = temp->data;
end = &((*end)->next);
temp = list_nth(temp, step);
}
return newlist; /* return the final stepped list */
}
(You probably want to factor a list_insert routine out of that that inserts a new
node at a given location. list_add isn't very useful since it always adds to the
beginning of the list.)

Resources