In our class right now we're covering nodes and linked lists, and are working on our first linked list program.
We've been given the following guidelines by the teacher:
Make sure your main function will accept 10 characters from STDIN and create a linked list with those characters (so your nodes will have a char member). Then, add an additional function called reverse. The purpose of the reverse function will be to create a copy of the linked list with the nodes reversed. Finally, print off the original linked list as well as the reversed linked list.
I've gotten it all written out, and I've compiled it with no errors - but the program doesn't work as intended, and I'm not entirely sure why. I'm sure it has something to do with how I've set up the pointers to "walk" the nodes - as the debug I put in shows it looping twice per user input letter. Specifications are that we're only supposed to use one function, and we pass a Node* to the function, and it returns the same. The function cannot print out anything - only make the second list that is a reverse of the first.
Any help would be greatly appreciated, I'm not terribly good at this yet and I'm sure I've made some rather silly mistakes.
#include <stdio.h>
#include <stdlib.h>
//struct declaration with self-reference to make a linked list
struct charNode {
char data;
struct charNode *nextPtr;
struct prevNode *prevPtr;
};
typedef struct charNode Node; //makes Node an alias for charNode
typedef Node *NodePtr; //makes NodePtr an alias for a pointer to Node (I think?)
//function declaration for a reverse function
Node* reverse(Node *stPtr);
int main(void)
{
//main function takes 10 letters and puts them in a linked list
//after that, it calls the reverse function to create a reversed list of those characters
//lastly it prints both lists
NodePtr newNode = NULL;
char input;
Node* revStart;
unsigned int counter = 0;
printf("Enter 10 letters to make a list: ");
NodePtr currentPtr = NULL; //sets currentPointer to startNode.
NodePtr previousPtr = NULL; //set previousPointer to null to start
while(counter<= 10)
{
scanf("%c", &input); //gather next letter
NodePtr newNode = malloc(sizeof(Node)); //creates a new node
if (newNode != NULL) //checks to make sure the node was allocated correctly
{
newNode->data = input; //makes the new node's data == input
newNode->nextPtr = NULL; //makes the nextPtr of the newNode NULL
}
currentPtr = newNode; //sets currentPtr to the address of the newNode
if(previousPtr == NULL) { //first time around previousPtr == NULL
newNode->nextPtr = newNode;
previousPtr = newNode; //sets previousPtr to the address of the new node (1st time only)
} else { //afterwards, currentPtr won't be NULL
previousPtr->nextPtr = currentPtr; //last node's pointer points to the current node
previousPtr = newNode; //update previous pointer to the current node
}
++counter;
//debug
printf("\nLoop #%d\n", counter);
}
revStart = reverse(newNode);
puts("The list is: ");
while (newNode != NULL){
printf("%c --> ", newNode->data);
currentPtr = currentPtr->nextPtr;
}
puts("NULL\n");
}
//reversing the nodes
Node* reverse(Node *stPtr)
{
//make a new node
NodePtr currentPtr = stPtr->nextPtr; //get the next letter ready (this will point to #2)
NodePtr prevRevPtr = NULL; //previous reverse node pointer
Node* revStart;
for(unsigned int counter = 1; counter <= 10; ++counter)
{
NodePtr revNode = malloc(sizeof(Node));
if(revNode != NULL) //if reverseNode is allocated...
{
if(prevRevPtr = NULL) //if previousReversePointer = NULL it's the "first" letter
{
revNode->data = stPtr->data; //letter = current letter
revNode->nextPtr = NULL; //this is the "last" letter, so NULL terminate
prevRevPtr = revNode; //previousReversePointer is this one
}else //after the first loop, the previous ReversePointer will be set
{
revNode->data = currentPtr->data; //set it's data to the pointer's data
revNode->nextPtr = prevRevPtr; //reverseNode's pointer points to last node entered
currentPtr = currentPtr->nextPtr; //moves to next letter
prevRevPtr = revNode; //changes previous reverse node to current node
if(counter == 10)//on the last loop...
{
revStart = revNode; //set revStart as a pointer to the last reverse node
//which is technically the "first"
}
}
}
}
return revStart;
}
Assuming your list is properly wired from inception, reversing a double-linked list is basically this:
Node *reverse(Node *stPtr)
{
Node *lst = stPtr, *cur = stPtr;
while (cur)
{
Node *tmp = cur->nextPtr;
cur->nextPtr = cur->prevPtr;
cur->prevPtr = tmp;
lst = cur;
cur = tmp;
}
return lst;
}
That's it . All this does is walk the list, swapping pointers, and retaining whatever the last node processed was. When done correctly the list will still be end-terminated (first node 'prev' is null, last node 'next' is null, and properly wired between.
I strongly advise walking a list enumeration through this function in a debugger. With each iteration watch what happens to cur as it marches down the list, to the active node's nextPtr and prevPtr values as their swapped, and to lst, which always retains the last-node processed. It's the new list head when done.
Okay so we don't need to contend with no line breaks in commments:
Node *reverse(Node *list) {
Node *rev = NULL;
while (list) {
Node *elt = list; // pop from the list
list = list->next;
elt->next = rev; // push onto reversed list.
rev = elt;
}
return rev;
}
As you wrote in comments, you probably don't need to have a previous pointer; you can just create a singly linked list.
There are several issues in your code, including:
When malloc returns NULL, you still continue with the loop -- only part of the code is protected by the if that follows, but not the rest. You should probably just exit the program when this happens.
Your algorithm does not maintain a reference to the very first node, i.e. the place where the linked list starts. When you print the list you should start with the first node of the list, but instead you start with newNode, which is the last node you created, so obviously not much will be printed except that last node. Moreover, both other pointers you have, will also point to the last node (currentPtr, previousPtr) when the loop ends.
newNode->nextPtr = newNode; temporarily creates an infinite cycle in your list. This is resolved in the next iteration of the loop, but it is unnecessary to ever make the list cyclic.
In the reverse function you have if(prevRevPtr = NULL)... You should get a warning about that, because that is an assignment, not a comparison.
Some other remarks:
The reverse function unnecessarily makes distinction between dealing with the first node and the other nodes.
It is also not nice that it expects the list to have 10 nodes. It would be better to just rely on the fact that the last node will have a NULL for its nextPtr.
It is a common habit to call the first node of a linked list, its head. So naming your variables like that is good practice.
As you are required to print both the initial list and the reversed list, it would be good to create a function that will print a list.
As you need to create new nodes both for the initial list and for the reversed list, it would be good to create a function that will create a node for you.
(I know that your teacher asked to create only one function, but this is just best practice. If this doesn't fit the assignment, then you'll have to go with the malloc-related code duplication, which is a pitty).
As you defined the type NodePtr, it is confusing to see a mix of Node* and NodePtr in your code.
Your question was first not clear on whether the reversal of the list should be in-place or should build a new list without tampering with the initial list. From comments it became clear you needed a new list.
I probably didn't cover all problems with the code. Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
struct charNode {
char data;
struct charNode *nextPtr;
};
typedef struct charNode Node;
typedef Node *NodePtr;
NodePtr reverse(Node *stPtr);
void printList(Node *headPtr);
NodePtr createNode(int data, NodePtr nextPtr);
int main(void) {
NodePtr headPtr = NULL; // You need a pointer to the very first node
NodePtr tailPtr = NULL; // Maybe a better name for currentPtr
printf("Enter 10 letters to make a list: ");
for (int counter = 0; counter < 10; counter++) {
char input;
scanf("%c", &input);
NodePtr newNode = createNode(input, NULL);
if (headPtr == NULL) {
headPtr = newNode;
} else {
tailPtr->nextPtr = newNode;
}
tailPtr = newNode;
}
NodePtr revHeadPtr = reverse(headPtr);
puts("The list is:\n");
printList(headPtr);
puts("The reversed list is:\n");
printList(revHeadPtr);
}
void printList(NodePtr headPtr) {
while (headPtr != NULL) {
printf("%c --> ", headPtr->data);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
puts("NULL\n");
}
NodePtr createNode(int data, NodePtr nextPtr) {
NodePtr newNode = malloc(sizeof(Node));
if (newNode == NULL) { // If malloc fails, exit the program
puts("Cannot allocate memory\n");
exit(1);
}
newNode->data = data;
newNode->nextPtr = nextPtr;
return newNode;
}
NodePtr reverse(NodePtr headPtr) {
NodePtr revHeadPtr = NULL;
while (headPtr != NULL) {
revHeadPtr = createNode(headPtr->data, revHeadPtr);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
return revHeadPtr;
}
Related
I am having a problem on assigning char array after I create a node.
I am having trouble on this function I created which it would make a new node and then assign character array into the created node. I don't have any problems when it comes to int but I can't seem to run when I switched to character array.
I get a run time error when I try to run my code.
Any help would be much appreciated.
Thank You!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct node{
char data[MAX];
struct node *next;
};
typedef struct node* nodePtr;
void create(nodePtr head, char data[]);
int main()
{
nodePtr head = NULL;
char str[] = "HELLO";
create(head, str);
return 0;
}
void create(nodePtr head, char data[])
{
if (head == NULL)
{
// empty list
head = (nodePtr) malloc(sizeof(struct node)); // create root
strcpy(head->data, data);
head->next = NULL;
}
else
{ // list not empty
nodePtr current = head; // start at the beginning...
while (current->next != NULL)
{
current = current->next; // walk to the end of the list
}
current->next = (nodePtr) malloc(sizeof(struct node));
current = current->next;
strcpy(current->data, data);
}
}
There is more than one problem with your program.
To begin with, when you add elements to a list that already has a head, are not initializing the next member. This will cause multiple list insertions to fail.
current->next = malloc(sizeof(struct node));
current = current->next;
strcpy(current->data, data);
current->next = NULL; //<-- you forgot this
The other big issue is that you are also leaking your entire list, because you pass the head pointer by value into the function. When the list is empty, the function modifies this value but it's a copy so when the function returns, the value of head in main is still NULL.
There are two options. Either you change your function to expect a pointer to the head-pointer, or you use what's called a "dummy head".
Using a dummy head actually simplifies lists a lot. What this means is your head is actually an unused node whose sole responsibility is to store the actual head in its next-pointer:
struct node head = {}; // dummy head node
create(&head, str);
The above will never actually hit the head == NULL part of the create function because dummy heads guarantee the head is always a valid node. So if you set your list up that way, then your create function can be simplified.
If you don't want to do this, then you need to pass a pointer to your head pointer. That means your create function becomes:
void create(nodePtr *head, char data[])
{
if (*head == NULL)
{
*head = malloc(sizeof(struct node));
strcpy((*head)->data, data);
(*head)->next = NULL;
}
else
{
nodePtr current = *head;
while (current->next != NULL) current = current->next;
current->next = malloc(sizeof(struct node));
current = current->next;
if (current != NULL)
{
strcpy(current->data, data);
current->next = NULL;
}
}
}
And you would invoke the above as:
nodePtr head = NULL;
create(&head, str);
One extra thing you might wish to do is make the function return the node that it created. The reason you might want to do this is that currently if you're inserting many items into the list you have to search to the end every time. If instead you pass the last node as the next head, then no searching is necessary:
nodePtr head = NULL;
nodePtr tail = head;
tail = create(head, "goodbye");
tail = create(tail, "cruel");
tail = create(tail, "world");
This would mean a small modification to your function, but I'm sure you can work that out.
So here I have created a C program to create and display a singly linked list.
#include <stdio.h>
#include <conio.h>
int main()
{
struct node
{
int data;
struct node *next;
};
struct node *head = malloc(sizeof(struct node));
struct node *temp = malloc(sizeof(struct node));
struct node *newnode;
int choice=1,count=0;
while(choice==1){
newnode=(struct node *)malloc(sizeof(struct node));
printf("Enter data");
scanf("%d",&newnode->data);
newnode->next=0;
if(head==0)
{
head=temp=newnode;
}
else
{
temp->next=newnode;
temp=newnode;
}
printf("\nDo you want to continue\n");
scanf("%d",&choice);
}
temp=head;
while(temp!=NULL){
printf("%d",temp->data);
temp=temp->next;
count++;
}
getch();
}
I'm not getting the desired output i.e. the linked list I am creating is not being displayed. Can someone please help me out and tell me where I went wrong?
Some comments on your code:
head should not start as a node instance: you don't have any value yet. It should start as NULL, which is also in line with the if condition you have in the loop. NULL represents an empty list, which is what you want to start with. Two problems are the consequence of this:
Since it isn't NULL at the start, the (head==0) condition is never true, and the loop never updates head. All the work done remains detached from this head node.
head references a node that is not initialised. Its value is undefined, and worse, its next reference is undefined. This leads to undefined behaviour during the print loop, where this next reference is used.
temp starts as a node instance, but as in the loop, temp is assigned temp->next, the code loses a reference to the original temp node. And each time temp progresses to the next, also the references to all other created nodes are lost.
temp is not a very useful name, as this variable has the same life time as head. In practice it represents the tail of the list in the first loop, so call it tail. The first point holds also for this tail: it should start as NULL
count is never used. Moreover, it should not be incremented during a print-job: that is mixing two jobs. Either count the nodes or print them, but don't do it together. Anyway, as this code has no use for this count, I'd just drop it.
It is better practice to use NULL when related to a pointer data type, not 0.
Separate functionality: now you have literally everything happening in one function: creating nodes, getting input, outputting nodes,... This is not maintainable. Separate different domains of functionality in separate functions.
If the only reason for include conio.h is to make that final getch call, presumably because you want to use to press enter at the end of the program, then just leave it out.
Here is some suggested code:
#include <stdio.h>
#include <stdlib.h>
// Define struct outside of main
struct node
{
int data;
struct node *next;
};
// Define some functions that perform common actions for a list
struct node *createNode(int data)
{
struct node *newnode = malloc(sizeof(struct node));
// Initialise the struct, so avoiding undefined behaviour
newnode->data = data;
newnode->next = NULL;
return newnode;
}
struct node *appendNode(struct node *tail, int data)
{
struct node *newnode = createNode(data);
if (tail != NULL) {
tail->next = newnode;
}
return newnode;
}
void printList(struct node *head)
{
while (head != NULL) {
printf("%d ", head->data); // Space between outputs
head = head->next; // head is a local variable, so we can change it
}
printf("\n"); // Terminate line
}
int main()
{
struct node *head = NULL; // Start with empty list
struct node *tail = NULL; // Better name. In beginning we don't have a tail
int choice = 1, data = 0;
while (choice == 1) {
// First get the data, and only then create the node
printf("Enter data: ");
scanf("%d", &data);
tail = appendNode(tail, data);
if (head == NULL) // Use NULL constant
{
head = tail;
}
printf("Do you want to continue? (0=no, 1=yes): ");
scanf("%d", &choice);
}
printList(head);
return 0;
}
I'm trying to build a singly-linked list using a struct with 2 data types: char* and int, as well as next to point to other nodes of course.
I have two functions: addToList, and printList as well as the main method to run everything.
What my code is supposed to do is add a node after the head, and check to see if another node with the same data has already been added. If so, it does not add the new node, while incrementing the count data of the already-linked node.
Then, printList() prints the count data and the char* data of each node.
The first issue is that my char comparison doesn't seem to be working, since duplicate nodes are still added. Then, my printList function does not print the char* data correctly. Here's my code (I made sure to comment it so it's easy to follow along):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struct for node. Has an extra data variable to keep track of which node is next
// in a singly-linked list.
typedef struct node {
char *str;
unsigned int count;
struct node *next;
} node;
// Creates a HEAD node with NULL data.
node *head = NULL;
// Adds a new node and populates the data.
struct node* addToList(struct node* Listptr, char* word){
struct node* new = malloc(sizeof(struct node));
new->str = malloc(sizeof(char) * 34);
strcpy(new->str, word);
new->count = 1;
new->next = Listptr;
// If the head is NULL, sets the new node as the head.
if(head == NULL){
head = new;
return new;
}
// Sets a node iterator "cur" to the first position.
node *cur = head;
// Sets a node iterator to be one place behind cur.
node *prev;
// Loops through the linked list, in order to count the previous words and determine
// if it is necessary to add another node.
// Otherwise, it sets cur to the next node, and prev to the node cur was just at.
while(cur != NULL){
if(cur->str == new->str){
cur->count++;
new = NULL;
return new;
} else{
prev = cur;
cur = cur->next;
}
}
// Checks to see if cur is NULL, if so, sets the previous node.next to the one we're adding.
if(cur == NULL){
prev->next = new;
return new;
}
}
// Prints out the count and word values of each node.
void printList(){
node* cur = head;
while(cur != NULL){
printf("%d %c\n", cur->count, cur->str);
cur = cur->next;
}
}
int main() {
node* Z = NULL;
char *a = "hello";
char *b = "world.";
char *c = "hello";
addToList(Z, a);
addToList(Z, b);
addToList(Z, c);
printList(Z);
return 0;
}
I expect to get:
2 hello
1 world
But in the console, I get:
1 l
1 (weird symbol)
1
Don't use == to compare strings rather use strcmp().
Change if (cur->str == new->str) to this:
if (strcmp(cur->str, new->str) == 0)
Read this to know more on string compare: How do I properly compare strings?
So I have a self-made double-linked-list implementation that is being used as a stand in for a queuer. (implemented in C, a language that I am admittedly weak in).
my typedef for the node:
typedef struct Node
{
char *name;
int data;
int recurring;
struct Node *next;
struct Node *prev;
}node;
which says "a node has a name, a datapoint, whether it's recurring or not and pointers to the previous and next nodes"
the insertion function like so
node * insertFromTail(node *tail, int data, int recurring, char *name)
{
node *newNode;
node *oldNext;
node *origTail = tail;
/*assume *pointer points to tail of list*/
/*printf("tail data is %d\n", tail->data);
printf("before loop\n");*/
while(tail->prev != NULL && tail->data > data)
{
/*printf("inside while loop\n");*/
tail = tail -> prev;
}
/*printf("after loop\n");*/
/*if we are looking at a no item list or tail*/
if(tail->next == NULL)
{
/*printf("pointer is tail\n");*/
return insert(tail, data, recurring, name);
}
else /*tail pointer points at item before the point of insertion*/
{
/*printf("default case\n");
printf("pointer data is %d\n", tail->data);*/
oldNext = tail->next;
newNode = (node *)malloc(sizeof(node));
newNode->data = data;
newNode->recurring = recurring;
newNode->name = name;
oldNext -> prev = newNode;
newNode -> next = oldNext;
tail -> next = newNode;
newNode -> prev = tail;
return origTail;
}
}
with the internal insert
node * insert(node *tail, int data, int recurring, char *name)
{
/* Allocate memory for the new node and put data in it.*/
tail->next = (node *)malloc(sizeof(node));
(tail->next)->prev = tail;
tail = tail->next;
tail->data = data;
tail->recurring = recurring;
tail->name = name;
tail->next = NULL;
return tail;
}
which is passed the tail of the list, the data point, the time at which the next item will recur at and the name of the item.
if we start with a node that is empty and has NULL prev and next references (a dummy node), and I add three unique nodes with a function called ADD that calls insertFromTail taking input from stdIn
int main()
{
node *start,*temp,*tail;
start = (node *)malloc(sizeof(node));
temp = start = tail;
temp->next = NULL;
temp->prev = NULL;
if(strcmp(command, "ADD") == 0)
{
scanf("%d",&argTime);
scanf("%s",&argName);
tail = insertFromTail(head, argTime, 0, *argName);
}
}
with input as so:
INPUT:
ADD 10 Gin
ADD 20 Vodka
ADD 30 Rum
PRINT
I would get an output of
OUTPUT:
Rum 10
Rum 20
Rum 30
This is an error, as the desired output would be
OUTPUT:
Gin 10
Vodka 20
Rum 30
I have a feeling it has to do with how the string is passed into the node, but as you can see, I'm stumped. This is the last thing left on the assignment and everything else is working perfectly, so I decided to ask here to see if anyone can nudge me on the right path. Thanks for your help in advance :)
P.S. Sorry for bad everything, I'm sleep deprived :(
Short answer: you'll need to duplicate that name:
tail->name = strdup(name);
Longer answer: at each iteration you're storing the same pointer. You're storing it and then the next time you're writing to it again. So you end up with 3 identical pointers to whatever you input last.
A simple fix is to duplicate the string and store a copy: precisely what strdup does. But if your implementation lacks strdup, you can try:
tail->name = malloc(strlen(name) + 1);
strcpy(tail->name, name);
Don't forget to check for errors
Don't forget to free the memory at some point
EDIT: Figured out the problem. Also if you found this through google or another search engine here is where I went wrong and how to fix it.
My deleteNode() method was moving through the list properly with the correct temp and keeping the head untouched. Where I was going wrong was in what I was returning as the result of the method. I was returning either temp or newNode which is incorrect because it goes through the list until it finds defined position. Once it finds that defined position it it would reassign the ->next pointer to point to the next->next> pointer which is correct but again I was returning the wrong thing. Because we had moved through the list using temp/NewNode we lost the header and we were returning the position we found and whatever was still in the next positions of the list.
How we fix this is returning the head (which is what is passed into the method). The reason why this works is because we have to understand how LinkedLists work. The pointers of each node point to the next node. Ex. we have a linked list |A|| - |B|| - |C|| - |D|| - |E|| - |F||
If we want to delete Node C we move to node B using the temp pointer and then assign the B->next to temp->next->next Thus skipping over C node and assigning D node.
NOTE: (From what I know this does not actually free the memory of C node so it isn't best practice because you can cause memory leaks this way) You should use the free() method on the C node.
Here is the code I ended up using
struct node* DeleteNode(struct node* head, int pos) {
struct node* temp = head;
int length = LinkedListLength(temp);
int i;
if(pos <= 0 || pos > length){
printf("ERROR: Node does not exist!\n");
}else{
if(pos == 1){
head = head->next; //move from head (1st node) to second node
}else{
for(i = 1; i < pos-1; ++i){ //move through list
temp = temp->next;
}
temp->next = temp->next->next;
}
}
return head;
}
Hopefully that helps understand how I went out fixing it.
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
ORIGINAL POST
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
EDIT: Note: This is a homework assignment I have spent a few days (estimated 4 hours) programming it I am just stuck on this one part. You can view my attempt below
I've been able to insert and delete from begining/end however I can't seem to get my delete node at position N in linkedlist to work.
My psuedocode looks like this:
LinkedList: 1,3,5,7,9,23
Grab LinkedList
Create new struct node A = head
Move through linkedlist until
position
Assign node to node->next
return linkedlist
EXAMPLE INPUT
Node structure
int data;
struct node* next;
int values[] = {1,3,5,7,9,23};
struct node* llist = CreateList(values,6);
llist = DeleteNode(llist, 1);
llist = DeleteNode(llist, 5);
llist = DeleteNode(llist, 3);
Which should leave the llist with the values 3, 5, 9 once the code has been run However, It is replacing the first node with a 0
Actual Code:
struct node* DeleteNode(struct node* head, int pos) {
struct node* temp = head;
struct node* newNode = head;
int length;
int i;
printf("DeleteNode: position = %d \nBefore: ", pos);
PrintList(temp);
if(pos <= 0){ //node does NOT exist
printf("ERROR: Node does not exist!\n");
}else{ //node DOES exist
length = LinkedListLength(temp);
if(length < pos){ //if length < position Node does not exist
printf("ERROR: Node does not exist!\n");
}else{
if(pos == 0){
newNode = temp->next;
}else if(pos == 1){
newNode = temp->next;
}else{
for(i = 1; i < pos; i++){
printf("i = %d\n", i);
temp = temp->next;
newNode->next;
}
if(temp->next == NULL){
newNode = NULL;
}else{
newNode = temp->next;
}
}
printf("After: ");
PrintList(newNode);
printf("\n");
}
}
return newNode;
}
EDIT #2: Code typo
Thanks for any help in advance. From what I have concluded my problem is that I am not moving through the list properly but I am unsure as to why I am not.
In your code, you have the line
newNode->next;
in your for loop. That operation doesn't do anything.
You also have
newNode-> = NULL;
which is not valid C, and I have no idea how you got that to compile.
But really, don't use that loop. A linked list is one of the most basic recursive data structures. As a result, almost all algorithms manipulating them are most elegant as a recursive solution.
typedef struct node node_t;
node_t* delete_at_index(node_t* head, unsigned i)
{
node_t* next;
if(head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i - 1), head); /* If it isn't the first element, we recursively check the rest. */
}
Removing a given node n from a singly-linked list can be boiled down to this operation:
Set the pointer that points to n to point instead to n->next.
You can break this down into two operations:
Find the pointer that points to n;
Set that pointer to n->next.
The complication arises because the pointer that points to n might either be the p->next field of the previous node in the list, or the head pointer (if n is the first node in the list).
Your code does not appear to be complete - it doesn't ever set the ->next field of any node to anything, so it's hard to say what's actually wrong.
// Remove list's node located at specified position.
// Arguments:
// head -- list's head
// pos -- index of a node to be removed (1-based!!!)
struct node* DeleteNode(struct node* head, int pos)
{
struct node* node;
struct node* prev;
int length;
int i;
printf("DeleteNode: position = %d \nBefore: ", pos);
PrintList(head);
// Check position's lower bound. Should be >= 1
if(pos <= 0) { //node does NOT exist
printf("ERROR: Node does not exist!\n");
return head;
}
// Seek to the specified node, and keep track of previous node.
// We need previous node to remove specified node from the list.
for(i=1, prev = 0, node = head; i < pos && node != 0; i++) {
prev = node;
node = node->next;
}
// Out of range
if(0 == node) {
printf("ERROR: Index out of bounds!\n");
return head;
}
// #node points to a list's node located at index pos
// #prev points to a previous node.
// Remove current node from the list.
if(0 == prev) {
head = node->next;
}
else {
prev->next = node->next;
}
free(node);
return head;
}
Your DeleteNode doesn't delete a node, it removes pos nodes from the front of the list. So you're trying to remove 9 items from a list that only contains 6, resulting of course in an empty list (NULL). Also, your code is overly complex and contains remnants of previous attempts. Please don't do that to yourself or to us; provide simple clean code and it will be easier to understand and to fix.
Figured out your for loop isn't reaching the desired position you wanted.
Better use equal to sign for the constraint it will work.
e.g.
for (i=1;i<=position-1;i++)
{
}