So im trying to append a list but every time I use the append function, it just crashes (SEG FAULT). I narrowed it down to around a line that in insert value and I marked it in the code below.
so here is the structs/lists
/*Declration of the struct*/
typedef struct Element {
value_type value;
Key_type key;
struct Element * next;
struct Element * sort;
}Node;
/*ADT declration*/
typedef struct List {
Node * head;
Node * head_sort;
Node * tail;
Node * tail_sort;
int size;
}Sorted_List;
Here is the rest of the code
/*Fucntion to add values ot the end using tail*/
int append_list (Sorted_List * List, value_type value, Key_type key){
int result = insert_value(List->tail, value, key) != NULL;
if ( result == SUCCESS){
List->size++;
List->tail = List->tail->sort;
}
return result;
}
int append (Sorted_List * List, value_type value, Key_type key){
return is_empty(List) ? push(List, value, key)
: append_list(List, value, key);
}
/*Function to insert value into list*/
Node * insert_value (Node * node, value_type value, Key_type key){
/*Setting a new node and mallocing it */
Node * new_node = malloc(sizeof(Node));
/*Checking for the new node to not equal null*/
if (new_node != NULL){
/*Setting the values for it*/
new_node->value = value;
new_node->key = key;
/*Setting the new node next to equal old nodes next*/
new_node->sort = node->sort;
/*Setting old node next to equal new node*/
node->sort = new_node;
/////I receive the error around this line^^^^/////
}
return new_node;
}
EDIT::
so here is the code for the push function used in the program
add front's job is to add the values rot the front
and find_prev_gt's job is to find the previes largest valus's location to add the new number
/*Function to push a value to to the front of the list*/
int push (Sorted_List * List, value_type value, Key_type key) {
Node * node = NULL;
int empty = 0;
empty = is_empty(List);
Node * next_node = NULL;
Node * insert_node = find_prev_gt(List->head, key);
int result = FAILURE;
if (insert_node == NULL) {
add_front(&(List->head), value,key);
}
else {
next_node = insert_node->sort;
if (next_node == NULL || next_node->key != key)
insert_value(insert_node, value,key);
}
result = (node != NULL );
/*Returns success if reseult is succesfull*/
if ( result == SUCCESS) {
List->size++;
if (empty)
List->tail = List->head;
}
return result;
}
Node * add_front(Node ** head, value_type value, Key_type key){
Node *new_node = malloc(sizeof(Node));
if (new_node != NULL) {
new_node->key = key;
new_node->value = value;
new_node->sort = *head;
*head = new_node; }
return new_node;
}
/*Function to check if list is empty*/
int is_empty (Sorted_List * list){
return list->head == NULL;
}
Node * find_prev_gt ( Node * head, Key_type key ) {
Node * node = head, * prev = NULL;
while (node != NULL && node->key < key){
prev = node;
node = node->sort;
}
return prev;
}
every time I use the append function, it just crashes
Your problem is in the function push where the value of node does not change after its initialization to NULL, so in
if ( result == SUCCESS) {
List->size++;
if (empty)
List->tail = List->head;
}
the test is always false and the associated code is not executed
You just need to change two lines, replace the line
add_front(&(List->head), value,key);
by
node = add_front(&(List->head), value,key);
and the line
insert_value(insert_node, value,key);
by
node = insert_value(insert_node, value,key);
If I do these two changes and I prefix your code by the definitions
#include <stdlib.h>
#include <stdio.h>
typedef int value_type;
typedef int Key_type;
#define SUCCESS 1
#define FAILURE 0
and add the following main :
int main()
{
Sorted_List list = { 0, 0, 0, 0, 0 };
Node * node;
append(&list, 2, 22);
append(&list, 3, 33);
append(&list, 1, 11);
for (node = list.head; node != NULL; node = node->sort)
printf("[key=%d, value=%d] ", node->key, node->value);
putchar('\n');
return 0;
}
the execution writes :
[key=22, value=2] [key=33, value=3] [key=11, value=1]
Out of that in Sorted_List your code change head and tail but not head_sort nor tail_sort but in Node you set sort but not next, this is not logical, furthermore the nodes are not sorted
Related
This is the struct definition.
typedef struct doubleLinkedList
{
struct doubleLinkedList *prevPtr;
int data;
struct doubleLinkedList *nextPtr;
} dNode;
typedef dNode *dNodePtr;
These are the functions performed on the struct
This is a function to create the double linked Node
dNodePtr create(int val) {
//Instantiate a new dNodePtr
dNodePtr newNode = (dNodePtr) malloc(sizeof(dNode));
newNode->data = val;
newNode->prevPtr = NULL;
newNode->nextPtr = NULL;
return newNode;
}
this is a function to append the double liked node
void append(dNodePtr* head, int val) {
//Check if the list's empty
if(!(*head)){
printf("Empty list: can't append...creating instead\n");
*head = create(val);
}
//Create a new Node to hold the value
dNodePtr valNode = (dNodePtr) malloc(sizeof(dNode)); //New Node
valNode->data = val; //Store value
valNode->nextPtr = NULL; //Terminate
dNodePtr aNode = *head; //Reference to head node
while(aNode->nextPtr){
aNode = aNode->nextPtr;
}
// Insert at end of list
valNode->prevPtr = aNode;
aNode->nextPtr = valNode;
}
This is a function to display the node via terminal.
void display(dNodePtr* head) {
dNodePtr aNode = *head;
printf("Printing\n");
while(!aNode){
printf("%d\n", aNode->data);
aNode = aNode->nextPtr;
}
printf("Done\n");
}
The function display is incorrect. The condition in the while statement will evaluate to logical true only when the pointer aNode is equal to NULL.
while(!aNode){
Instead you have to write
while( aNode ){
The function append is also incorrect. When initially the list is empty that is the pointer to the head node is equal to NULL the function creates two nodes with the same value
if(!(*head)){
printf("Empty list: can't append...creating instead\n");
*head = create(val);
}
//Create a new Node to hold the value
dNodePtr valNode = (dNodePtr) malloc(sizeof(dNode)); //New Node
//...
Also outputting a message in this case does not make a sense.
The function can be defined at least like
void append(dNodePtr* head, int val) {
//Check if the list's empty
if( *head == NULL ){
*head = create(val);
}
else
{
dNodePtr aNode = *head; //Reference to head node
while(aNode->nextPtr){
aNode = aNode->nextPtr;
}
// Insert at end of list
aNode->nextPtr = create(val);
aNode->nextPtr->prevPtr = aNode;
}
}
This is the code I tried writing down to add an element in a double linked list, that takes an index and a value and adds a new element to the original list.
It is taking index and value but just adds the elements I give like a stack.
node *add(node *head, int index, int val)
{
node *new = create(val);
node *temp = malloc(sizeof(node));
if (head == NULL)
{
head = new;
temp = head;
//printf(": %d",temp->data);
}
temp = head;
int i = 1;
while (i < (index - 1) && (temp->next != NULL))
{
i++;
temp = temp->next;
}
temp->next = new;
new->next = NULL;
new->prev = temp;
return head;
}
however this code(for a doubly linked list) just adds elements one after the other, disregarding the index passed.
My prof gave us a code for a singly linked list where he did something similar.
struct Node *insert(struct Node *listp, int pos, int info)
{
/*Inserts a Node in list at position pos with data info
pos>0. If pos>list length then new node added at end.
If pos<1 adds at beginning.
*/
struct Node *new=malloc(sizeof(struct Node)), *prev;// new is the new node we create everytime.
//create new node and initialize fields
new->data=info;
new->next=NULL;
if (listp==NULL) listp=new;
else
if (pos<=1) { //negative or 1 index.
new->next=listp; //first node bann gaya new
listp=new; //head is pointing at new
}
else {
//pos>1. Go to node at pos-1.
prev=listp;
int i=1;
while ((i++<pos-1) && prev->next!=NULL) { //indexing
prev=prev->next;
}
new->next=prev->next;
prev->next=new;
}
return listp;
}
how do I address this problem?
To implement a doubly linked list, your node needs to have pointers to the previous node and next node, then you can write something almost as similar to what your professor gave you for single linked list:-
#include <stdlib.h>
#include <stdio.h>
//Doubly linked list Node
typedef struct Node{
int info;
struct Node* next;
struct Node* prev;
} Node;
Node* insert(Node* listp, int pos, int info){
//Allocate memory for node and its previous neighbor
Node* new = malloc(sizeof(Node));
Node* prev = malloc(sizeof(Node)), *tail;
//initialize new node with these values
new->info = info;
new->next = NULL;
new->prev = NULL;
//if head doesn't exist then create one
if(listp == NULL){
/*
listp gets whatever new had, ie
listp->info = info
listp->next = NULL
listp->prev = NULL
*/
Node* tail = malloc(sizeof(Node));
tail->info = 0;
tail->next = NULL;
tail->prev = NULL;
listp = new;
listp->next = tail;
tail->prev = listp;
}
//Lets Loop through the List and insert node at pos
else {
if(pos <= 1){
/*
This should replace the current head
listp = new
*/
new->next = listp;
new->prev = listp->prev;
listp->prev = new;
listp = new;
}
else{
int i = 2;
prev = listp->next;
printf("%d\n", prev->prev->info);
while(i != pos){
printf("%d\n", new->info);
prev = prev->next;
i++;
}
new->next = prev;
new->prev = prev->prev;
prev->prev->next = new;
prev->prev = new;
}
}
return listp;
}
// Test case
int main(){
Node* listp;
listp = insert(NULL, 0, 2);
listp = insert(listp, 1, 3);
listp = insert(listp, 2, 5);
Node* cnt = listp;
printf("|");
while(cnt->next != NULL){
printf("--%d-->", cnt->info);
cnt = cnt->next;
}
printf("\n");
}
Try that. Make any typo corrections if any
#include <stdio.h>
#include <stdlib.h>
/**
* add_node_end - adds a new node at the end of a dllist list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_end(node **head, const int n)
{
node *new, *temp;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->next = NULL;
if (*head == NULL)
{
new->prev = NULL;
*head = new;
return (*head);
}
temp = *head;
while (temp->next)
{
temp = temp->next;
}
temp->next = new;
new->prev = temp;
return (new);
}
/**
* add_dnodeint - adds a new node at the beginning of a dlistint_t list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_start(node **head, const int n)
{
node *new;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->prev = NULL;
if (*head == NULL)
{
new->next = NULL;
*head = new;
return (*head);
}
new->next = *head;
(*head)->prev = new;
*head = new;
return (*head);
}
/**
* node_len - returns the number of elements in a dllist list
* #h: head of doubly linked list
*
* Return: number of nodes
*/
size_t node_len(const node *h)
{
int count = 0;
while (h)
{
count++;
h = h->next;
}
return (count);
}
/**
* insert_dnodeint_at_index - inserts a new node at a given position
* #h: a pointer to a pointer of the first node of node linked list
* #index: the position to add the new node
* #val: the data n of the new node
* Return: if the function fails = NULL
* otherwise - the address of the new node/element
*/
node *insert_dnodeint_at_index(node **h, unsigned int index, int val)
{
node *newNode, *current;
size_t list_length;
unsigned int i = 0;
if (h == NULL)
return (NULL);
if (index == 0)
return (add_node_start(h, n));
list_length = node_len(*h);
if (index == (list_length - 1))
return (add_node_end(h, n));
newNode = malloc(sizeof(node));
if (newNode == NULL)
return (NULL);
newNode->val = val;
if (*h == NULL)
{
newNode->prev = NULL;
newNode->next = NULL;
return (newNode);
}
current = *h;
while (current)
{
if (i == index)
{
newNode->next = current;
newNode->prev = current->prev;
current->prev->next = newNode;
current->prev = newNode;
return (newNode);
}
current = current->next;
i++;
}
free(newNode);
return (NULL);
}
The function below is the one I am trying to work on. The problem I am running into is that I do not know how to "keep" the pointer to the original head to the list as that is what I have to return after insertion.
There is no Driver code so everything must be done inside this function.
Because I must do this recursively I cannot just create a temporary node to point to the original head. I am just getting used to recursion and I cannot find a solution.
NOTE: There are some other problems with my function as I believe it wouldn't work well for inserting a new node into the beginning and end of the linked list but I am confident I could work out those edge cases.
The main thing I am trying to learn is how to "store" the original head of my list.
All help is appreciated.
Node* insert(Node* head, int index, int data)
{
if (head == NULL) return NULL; // if list is empty
if (index == 1) // if we have accessed node before insertion
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->next = head->next; // new_node->next now links to the node next in the list
head->next = new_node; // head->next links to new node
new_node->data = data; // assigns new node its data
return head; // not sure how to return original head
}
return insert(head->next, index - 1, data);
}
Node *insertRecursive(Node* head,int pos,int val)
{
if(pos==0 || head==NULL)
{
Node *newNode= new Node(val);
newNode->next=head;
head=newNode;
return head;
}
else
head->next = insertRecursive(head->next,pos-1,val);
}
For starters the parameter that specifies the position where a node has to be inserted should have an unsigned integer type, for example, size_t. Positions should start from 0.
The function can be defined the following way
struct Node * insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0 )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
new_node->next = head;
new_node->data = data;
head = new_node;
}
else
{
head->next = insert( head->next, pos - 1, data );
}
return head;
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node * insert( struct Node *head, size_t pos, int data )
{
if (head == NULL || pos == 0)
{
struct Node *new_node = malloc( sizeof( struct Node ) );
new_node->next = head;
new_node->data = data;
head = new_node;
}
else
{
head->next = insert( head->next, pos - 1, data );
}
return head;
}
void print( const struct Node *head )
{
for (; head != NULL; head = head->next)
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main( void )
{
struct Node *head = NULL;
head = insert( head, 0, 3 );
print( head );
head = insert( head, 0, 0 );
print( head );
head = insert( head, 1, 1 );
print( head );
head = insert( head, 2, 2 );
print( head );
}
The program output is
3 -> null
0 -> 3 -> null
0 -> 1 -> 3 -> null
0 -> 1 -> 2 -> 3 -> null
Node* insert_Node_recursively(Node* head,int data,int position){
//Inserting on the first node.
if(position==0){
Node* newNode=new Node(data);
newNode->next=head;
head=newNode;
return head;
}
if((head->next==NULL && position==0) /*for adding on the end of the list */ || position==1 /*Inserting on node in between */){
Node* newNode=new Node(data);
newNode->next=head->next;
head->next=newNode;
return head;
}
//in case the position exceeds the total number of nodes
if(head->next==NULL && position>0){
return head;
}
else{
head->next=insert_Node_recursively(head->next,data,position-1);
}
return head;
}
this will work I think, covered all the aspects
//if you have created a node using class then here is the solution
//to insert a node at a position recurssively
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//here is the full solution to add a node recursively at a position
#include<iostream>
using namespace std;
//the below code is for creation of class for node
class Node
{
public:
int data;
Node * next;
Node(int data) //constructor
{
this -> data = data;
next = NULL;
}
};
//the below code is for creation of linked list
//a terminator -1 is used to stop taking input
Node * takeInput()
{
int data;
cout<<"Enter the data of the node to be inserted ( use -1 to terminate
the insertion ) : ";
cin>>data;
Node * head = NULL;
Node * tail = NULL;
while(data != -1)
{
Node * newNode = new Node(data);
if(head == NULL)
{
head = newNode;
tail = newNode;
}
else
{
tail->next=newNode;
tail = tail -> next;
}
cout<<"Enter the data of the node to be inserted ( use -1 to
terminate the insertion ) : ";
cin>>data;
}
return head;
}
//the below code is to print the linked list
void print(Node * head)
{
if(head == NULL)
{
cout<<"The linked list id empty !"<<endl;
return;
}
Node * temp = head;
while(temp != NULL)
{
cout<<temp->data<<" ";
temp = temp -> next;
}
cout<<endl;
}
//the below part is the main solution to the problem
//insertion at a position using recursion
Node * insertRecursive(Node * head, int data , int key)
{
if (head == NULL || key == 0)
{
Node * newNode = new Node(data);
newNode -> next = head;
head = newNode;
}
else
{
head -> next = insertRecursive(head -> next , data , key - 1);
}
return head;
}
//this is the main from where all the function calls happen
int main()
{
int data, key;
Node * head = takeInput();
print(head);
cout<<"Enter the data of the node to be inserted : ";
cin>>data;
cout<<"Enter the position of insertion : ";
cin>>key;
head = insertRecursive(head,data,key);
print(head);
}
Suppose we have doubly linked list of nodes
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
struct Node* prev;
} Node;
typedef struct LinkedList {
Node *first;
Node *last;
} LinkedList;
void initList(LinkedList* l) {
l->first = NULL;
l->last = NULL;
}
and I have to code method, which inserts a new node with given value to the end of the list and returns a pointer to the new node. My attempt follows:
Node *insert(LinkedList *list, int value) {
Node node;
node.value = value;
node.prev = list->last;
node.next = NULL;
if (list->last != NULL){
(list->last)->next = &node;
}else{
list->first = &node;
list->last = &node;
}
return &node;
}
It seems, that insertion in the empty list works, but it doesn't for a non-empty one.
(There are implementation tests, which tell me if an insertion was successful or not. I can post the codes of them, but don't think it's important).
So please, where are the mistakes?
There is a warning in the log (the 51st line is that with 'return &node')
C:\...\main.c|51|warning: function returns address of local variable [-Wreturn-local-addr]|
Is that serious problem? And how to remove it?
Thank you for the answers, but I think there is still a problem with non-empty lists, because according to the test, this fails:
void test_insert_nonempty(){
printf("Test 2: ");
LinkedList l;
initList(&l);
Node n;
n.value = 1;
n.next = NULL;
l.first = &n;
l.last = &n;
insert(&l, 2);
if (l.last == NULL) {
printf("FAIL\n");
return;
}
if ((l.last->value == 2) && (l.last->prev != NULL)) {
printf("OK\n");
free(l.last);
}else{
printf("FAIL\n");
}
}
Node node; is a local variable in your function insert. It is "destroyed" as soon as your function terminates and is not longer defined. Returning a pointer to local variable of a function is undefined behavior. You have to allocate dynamic memory. Dynamically allocate memory is reserved until you free it:
Node *insert(LinkedList *list, int value) {
Node *node = malloc( sizeof( Node ) ); // allocate dynamic memory for one node
if ( node == NULL )
return NULL; // faild to allocate dynamic memory
node->value = value;
node->prev = list->last;
node->next = NULL;
if ( list->first == NULL )
list->first = node; // new node is haed of list if list is empty
else // if ( list->last != NULL ) // if list->first != NULL then list->last != NULL
list->last->next = node; // successor of last node is new node
list->last = node; // tail of list is new node
return node;
}
Note to avoid memory leaks you have to free each node of the list, when you destroy the list.
You are returning address of non-static local variable which will vanish on returning from function, and dereferencing the address after returning from the function invokes undefined behavior.
You have to allocate some buffer and return its address.
Node *insert(LinkedList *list, int value) {
Node *node = malloc(sizeof(Node));
if (node == NULL) return NULL;
node->value = value;
node->prev = list->last;
node->next = NULL;
if (list->last != NULL){
(list->last)->next = node;
}else{
list->first = node;
list->last = node;
}
return node;
}
You have to allocate the new node dynamically.
Otherwise variable node in your function
Node *insert(LinkedList *list, int value) {
Node node;
//...
is a local variable of the function that will not be alive after exiting the function. As result any pointer to the variable used to access it will be invalid.
The function can look like
Node * insert( LinkedList *list, int value )
{
Node *node = malloc( sizeof( Node ) );
if ( node != NULL )
{
node->value = value;
node->prev = list->last;
node->next = NULL;
if ( list->last != NULL )
{
list->last->next = node;
}
else
{
list->first = node;
}
list->last = node;
}
return node;
}
I don't know how to delete the first and last element in a linked list in c. Below is my program, that uses a linked list. I have no idea how to actually delete the last element but I am able to find it. the element consists of an integer and the next pointer. if someone could please help me, it would be much appreciated.
struct ListNode{
int value;
struct ListNode *next;
};
typedef struct ListNode Link;
void deleteLast(Link *);
void printList(Link *);
void deleteFirst(Link *);
int main(){
Link *myList;
Link *curr, *newlink;
int i;
curr = myList;
for(i = 0; i < 10; i++){
newlink = (Link*) malloc(1*sizeof(Link));
newlink->value = i*i;
curr->next = newlink;
curr = newlink;
}
curr->next = NULL;
curr = myList->next;
deleteFirst(curr);
printList(curr);
printf("\n");
}
void deleteLast(Link *head)
{
Link *curr;
curr = head->next;
while (curr->next!=NULL)
{
curr = curr->next;
}
free(curr->next);
curr->next = NULL;
}
void printList(Link *head){
Link *curr;
curr = head->next;
printf("[");
if(curr!=NULL){
printf("%d",curr->value);
curr = curr->next;
}
while(curr != NULL){
printf(", %d", curr->value);
curr = curr->next;
}
printf("]\n");
}
void deleteFirst(Link *head){
Link *curr;
curr = head->next;
free(curr->value);
free(curr->next);
printf("%d\t",curr->value);
}
Nothing I try works, please can you help me.
You have many errors in your code.
When you create your list:
You don't have to cast the return value of malloc
You are doing curr->next = newlink; where curr = myList with initialized value. You can change your loop to
Link *myList = NULL;
Link *curr, *newlink;
int i;
curr = myList;
for(i = 0; i < 10; i++){
newlink = malloc(1*sizeof(Link));
newlink->value = i*i;
if (curr != NULL)
curr->next = newlink;
else
myList = newlink;
curr = newlink;
}
When you remove the last element you are going to far, that's why it's not working
Link *curr;
curr = head->next;
while (curr->next != NULL) {
head = curr;
curr = curr->next;
}
free(head->next);
head->next = NULL;
When you want to remove the first element of your list
You don't have to free the field value since you have not allocated it with malloc
Even if you remove the first element of your list, you are not changing the value of the begining of your list in the main. It's why you must take as a param a Link**
void deleteFirst(Link **head){
Link *curr;
curr = (*head)->next;
free(*head);
*head = curr;
}
And you can call this function from the main by giving the address of the beginning of your list:
deleteFirst(&myList);
deleteLast(myList);
printList(myList);
of course in all your functions you must check if you have at least some values in the list and not an empty pointer NULL
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct node Node;
struct node{
int element;
Node *next;
};
Node* head = NULL;
bool put(int data)
{
bool retVal = false;
Node* temp;
do
{
if (head == NULL)
{
head = malloc(sizeof(Node));
if (head)
{
printf("New head created\n");
head->element = data;
head->next = NULL;
printf("Element %d stored\n", data);
retVal = true;
break;
}
else
{
printf("Could not create new head\n");
break;
}
}
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = malloc(sizeof(Node));
temp->next->element = data;
temp->next->next = NULL;
printf("Element %d stored\n", data);
retVal = true;
break;
} while(1);
return retVal;
}
bool get(int *pData)
{
bool retVal = false;
Node* temp;
if (head != NULL)
{
retVal = true;
Node *prevNode = head;
temp = prevNode;
while (temp->next)
{
prevNode = temp;
temp = temp->next;
}
*pData = temp->element;
printf("Element %d retrieved\n", *pData);
free(temp);
printf("Node freed\n");
if (temp == head)
{
head = NULL;
}
else
{
prevNode->next = NULL;
}
}
return retVal;
}
int main(void)
{
int retrievedNum;
int num;
for (num = 0; num < 5; num++)
{
put(num);
}
printf("\n");
for (num = 0; num < 6; num++)
{
get(&retrievedNum);
}
put(num);
get(&retrievedNum);
printf("Element retrieved: %d\n", retrievedNum);
return 1;
}
This code will work for deleting last element in linklist:
void dellast()
{
r=head;
struct node* z;
do
{
z=r;
r=r->next;
if(r->next==NULL)
{
z->next=NULL;
free(r->next);
}
}while(z->next!=NULL);
}
The Code works like this:
Keep the track of current node and its previous node.
If current->next==NULL means it is the last node.
So do previous->next=NULL and free the current node
I've made my own (singly) LinkedList example in C, its proven to work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/********** GLOBALS *******************************/
#define OK 0
#define ERROR -1
/********** STRUCT AND TYPES DEFINTIONS ***********/
/* a node with key, data and reference to next node*/
typedef struct Node {
int key;
char string[1024];
struct Node *next; // pointer to next node
} Node;
/* the actual linked list: ref to first and last Node, size attribute */
typedef struct LinkedList {
struct Node *first;
struct Node *last;
int size;
} LinkedList;
/********** FUNCTION HEADERS **********************/
LinkedList* init_list();
void insert_end(LinkedList *list, int key, char string[]);
void insert_beginning(LinkedList *list, int key, char string[]);
int remove_end(LinkedList *list);
int remove_beginning(LinkedList *list);
int print_list(LinkedList *list);
void free_list(LinkedList *list);
char * get_string(LinkedList *list, int key);
/*********** FUNCTION DEFINITIONS ***************/
/**
* init_list Returns an appropriately (for an empty list) initialized struct List
*
* #return LinkedList * ..ptr to the newly initialized list
*/
LinkedList * init_list() {
printf("initializing list...\n");
LinkedList *list = (LinkedList*) malloc(sizeof(LinkedList));
list->first = NULL;
list->last = NULL;
list->size = 0;
return list;
}
/**
* Given a List, a key and a string adds a Node containing this
* information at the end of the list
*
* #param list LinkedList * ..ptr to LinkedList
* #param key int .. key of the Node to be inserted
* #param string char[] .. the string of the Node to be inserted
*/
void insert_end(LinkedList *list, int key, char string[]) {
printf("----------------------\n");
list->size++; // increment size of list
// intialize the new Node
Node* newN = (Node*) malloc(sizeof(Node));
newN->key = key;
strcpy(newN->string, string);
newN->next = NULL;
Node* oldLast = list->last; // get the old last
oldLast->next = newN; // make new Node the next Node for oldlast
list->last = newN; // set the new last in the list
printf("new Node(%p) at end: %d '%s' %p \n", newN, newN->key, newN->string,newN->next);
}
/**
* Given a List, a key and a string adds a Node, containing
* this information at the beginning of the list
*
* #param list LinkedList * ..ptr to LinkedList
* #param key int .. key of the Node to be inserted
* #param string char[] .. the string of the Node to be inserted
*/
void insert_beginning(LinkedList *list, int key, char string[]) {
printf("----------------------\n");
list->size++; // increment size of list
Node* oldFirst = list->first; //get the old first node
/* intialize the new Node */
Node* newN = (Node*) malloc(sizeof(Node));
newN->key = key;
strcpy(newN->string, string);
newN->next = oldFirst;
list->first = newN; // set the new first
/* special case: if list size == 1, then this new one is also the last one */
if (list->size == 1)
list->last = newN;
printf("new Node(%p) at beginning: %d '%s' %p \n", newN, newN->key,newN->string, newN->next);
}
/**
* Removes the first Node from the list
*
* #param list LinkedList * .. ptr to the List
*
* #return OK | ERROR
*/
int remove_beginning(LinkedList *list) {
printf("----------------------\n");
if (list->size <= 0)
return ERROR;
list->size--;
Node * oldFirst = list->first;
printf("delete Node(%p) at beginning: '%d' '%s' '%p' \n", oldFirst,oldFirst->key, oldFirst->string, oldFirst->next);
free(list->first); //free it
list->first = oldFirst->next;
oldFirst = NULL;
return OK;
}
/**
* Removes the last Node from the list.
*
* #param list LinkedList * .. ptr to the List
*
* #return OK | ERROR
*/
int remove_end(LinkedList *list) {
printf("----------------------\n");
/* special case #1 */
if (list->size <= 0)
return ERROR;
/* special case #2 */
if (list->size == 1) {
free(list->first);
list->first = NULL;
list->last = NULL;
return OK;
}
printf("delete Node(%p) at end: '%d' '%s' '%p' \n", list->last,list->last->key, list->last->string, list->last->next);
list->size--; // decrement list size
Node * startNode = list->first;
/* find the new last node (the one before the old last one); list->size >= 2 at this point!*/
Node * newLast = startNode;
while (newLast->next->next != NULL) {
newLast = newLast->next;
}
free(newLast->next); //free it
newLast->next = NULL; //set to NULL to denote new end of list
list->last = newLast; // set the new list->last
return OK;
}
/**
* Given a List prints all key/string pairs contained in the list to
* the screen
*
* #param list LinkedList * .. ptr to the List
*
* #return OK | ERROR
*/
int print_list(LinkedList *list) {
printf("----------------------\n");
if (list->size <= 0)
return ERROR;
printf("List.size = %d \n", list->size);
Node *startN = list->first; //get first
/* iterate through list and print contents */
do {
printf("Node#%d.string = '%s', .next = '%p' \n", startN->key,startN->string, startN->next);
startN = startN->next;
} while (startN != NULL);
return OK;
}
/**
* Given a List, frees all memory associated with this list.
*
* #param list LinkedList * ..ptr to the list
*/
void free_list(LinkedList *list) {
printf("----------------------\n");
printf("freeing list...\n");
if (list != NULL && list->size > 0) {
Node * startN = list->first;
Node * temp = list->first;
do {
free(temp);
startN = startN->next;
temp = startN;
} while (startN != NULL);
free(list);
}
}
/**
* Given a List and a key, iterates through the whole List and returns
* the string of the first node which contains the key
*
* #param list LinkedList * ..ptr to the list
* #param key int .. the key of the Node to get the String from
*
* #return OK | ERROR
*/
char * get_string(LinkedList *list, int key) {
printf("----------------------\n");
Node *startN = list->first; //get first
/* iterate through list and find Node where node->key == key */
while (startN->next != NULL) {
if (startN->key == key)
return startN->string;
else
startN = startN->next;
}
return NULL;
}
/*************** MAIN **************/
int main(void) {
LinkedList *list = init_list();
insert_beginning(list, 1, "im the first");
insert_end(list, 2, "im the second");
insert_end(list, 3, "im the third");
insert_end(list, 4, "forth here");
print_list(list);
remove_end(list);
print_list(list);
remove_beginning(list);
print_list(list);
remove_end(list);
print_list(list);
printf("string at node with key %d = '%s' \n",2,get_string(list, 2));
free_list(list);
return OK;
}
Hope this implementation example helps.