typedef struct Element
{
int number;
struct Element *right;
struct Element *left;
} Element;
Element *newElement;
Element *head;
Element *pos;
Element *current;
void insert_Element()
{
newElement = malloc(sizeof(Element));
if (head==NULL)
{
head = newElement;
current = newElement;
current->right = pos;
//pos->left = current;
}
}
The head of the double-linked-list should have a pointer to the next (right) element (which is NULL, but also pos). This works fine, but the pointer back(left) from pos/NULL doesn't work.
What did I do work; Is it even possible?
Thank you in advance :)
The present version of the insert_Element function does not work unless head is NULL and pos is not NULL, and it does not set the left member of the new element. The purpose of the pos variable has not been stated, but appears to be used to point to the element before which the new element is to be inserted. We could use pos == NULL to indicate that the new element is to be placed at the end of the list. Here is a version that does that:
void insert_Element(void)
{
newElement = malloc(sizeof(Element));
if (newElement == NULL)
{
return;
}
newElement->right = pos;
if (pos != NULL)
{
/* insert before pos */
newElement->left = pos->left;
pos->left = newElement;
}
else if (head != NULL)
{
/* add to end of list */
current = head;
while (current->right != NULL)
{
current = current->right;
}
newElement->left = current;
current->right = newElement;
}
else
{
/* add to empty list */
newElement->left = NULL;
}
if (pos == head)
{
/* make it the start of the list */
head = newElement;
}
/* make it the 'current' element */
current = newElement;
}
It is better not to use global variables so much and uses function parameters instead. Here is a version that uses no global variables and returns a pointer to the new element on the list (or NULL on allocation failure):
Element *insert_Element(Element **phead, Element *pos)
{
Element *newElement = malloc(sizeof(Element));
if (newElement == NULL)
{
return NULL;
}
newElement->right = pos;
if (pos != NULL)
{
/* insert before pos */
newElement->left = pos->left;
pos->left = newElement;
}
else if (*phead != NULL)
{
/* add to end of list */
Element *current = *phead;
while (current->right != NULL)
{
current = current->right;
}
newElement->left = current;
current->right = newElement;
}
else
{
/* add to empty list */
newElement->left = NULL;
}
if (pos == *phead)
{
/* make it the start of the list */
*phead = newElement;
}
return newElement;
}
It's possible you just need to allocate you Element *pos. Actually pos is equal to NULL and logically don't have pointer left or right, it's like looking for the toilet in a house that doesn't exist.
Related
int add_after(ITEM *list, ITEM *c_item, int value)
{
//create a new node
ITEM *elem = malloc(sizeof(ITEM));
elem->value = value;
//if head is NULL, it is an empty list
if (elem == NULL || c_item == NULL || list == NULL) {
return -1;
} else {
while (list != NULL) {
if (list == c_item) {
elem->next = list->next;
elem->value = value;
list->next = elem;
list = list->next;
}
list = list->next;
}
}
return 0;
}
I am trying to make a function the puts a node after an existing node. my problem is inside the else statement. I am trying to find a node list equal to node c_item. After finding the equal, it should enter elem in between them.
I would rewrite your function as follow:
int add_after(ITEM *list, ITEM *c_item, int value)
{
//create a new node
ITEM *elem;
//if head is NULL, it is an empty list
if (!list || !c_item) {
return -1;
}
/* Create a new node. */
elem = malloc(sizeof(ITEM));
if (!elem) {
return -1;
}
/* You should rather set the value after having checked the allocated
* memory is not NULL. */
elem->value = value;
/* Insert elem ahead of the current item. */
elem->next = c_item->next;
c_item->next = elem;
return 0;
}
If you wish to insert a new node after a given node, you do not need to iterate on the list, just insert the new node as the next node of the c_item node:
int add_after(ITEM *list, ITEM *c_item, int value) {
//check function arguments
if (list == NULL || c_item == NULL)
return -1;
//create a new node
ITEM *elem = malloc(sizeof(ITEM));
if (elem == NULL)
return -1;
elem->value = value;
elem->next = c_item->next;
c_item->next = elem;
return 0;
}
In your approach, you try and locate the element in the list, which might be necessary if the caller cannot be trusted. In this case, you should have a different return value whether the element was inserted or not and free the allocated elem if c_item was not found:
int add_after(ITEM *list, ITEM *c_item, int value) {
//create a new node
ITEM *elem = malloc(sizeof(ITEM));
//if head is NULL, it is an empty list
if (elem == NULL || c_item == NULL || list == NULL) {
return -1;
} else {
while (list != NULL) {
if (list == c_item) {
elem->value = value;
elem->next = list->next;
list->next = elem;
return 1; // element was inserted
}
list = list->next;
}
free(elem);
return 0; // c_item was not found, elem not inserted
}
}
I am trying to implement an algorithm in C which splits a linked list. So what I am trying to do is, I have a linked list of all entries, I am trying to split that linked list into two separate lists based on distance of elements from a specific node.
What shiftAndCluster does is takes in a linked list list, 2 empty lists oldFreshList and newList and 2 nodes best1 and best2. It first searches for these 2 nodes in list and pushed them into 2 empty lists respectively. Then the function iterates over each node of list and calculates its distance from either of the nodes and pushes it to the list containing the closer best node.
The code goes like this
void shiftAndCluster(SinglyLinkedList* list, SinglyLinkedList* oldFreshList, SinglyLinkedList* newList, SinglyLinkedListNode *best1, SinglyLinkedListNode *best2)
{
SinglyLinkedListNode *curr1 = list->front;
SinglyLinkedList *temp = cloneFullList(list);
SinglyLinkedListNode *prev = curr1;
while (curr1 != NULL)
{
if (curr1 == best2)
{
break;
} //reach till best2 in the list, so we have the prev of best2 with us
prev = curr1;
curr1 = curr1->next;
}
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(newList,curr1);
}
curr1 = list->front;
prev = curr1;
while(curr1 != NULL)
{
if (curr1 == best1) {
// break when found best1
break;
};
prev = curr1;
curr1 = curr1->next;
}
// first, middle and last
if (prev == curr1)
{
list->front = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
else
{
prev->next = curr1->next;
list->size--;
SinglyLinkedList_pushFront(oldFreshList,curr1);
}
int firstSize = 1;
int secondSize = 1;
curr1 = list->front;
double dist1, dist2;
while (curr1 != NULL && list->size)
{
curr1=list->front;
SinglyLinkedList_popFront(list);
dist1 = calculateDistance(curr1,best1);
dist2 = calculateDistance(curr1,best2);
if (dist1 < dist2)
{
SinglyLinkedList_pushFront(oldFreshList,curr1);
firstSize++;
if (firstSize == 10) break;
}
else
{
SinglyLinkedList_pushFront(newList,curr1);
secondSize++;
if (secondSize == 10) break;
}
}
list->front = temp->front;
list->size = temp -> size;
}
The size of list is 11 nodes so the algorithm stops when either of the new list reaches size 10. At the end, the old list is repopulated with it's original entries.
The struct has been defined as
typedef struct SinglyLinkedListNode
{
void *data;
struct SinglyLinkedListNode *next;
}SinglyLinkedListNode;
typedef struct SinglyLinkedList
{
int size;
struct SinglyLinkedListNode *front;
}SinglyLinkedList;
Helper functions are:
SinglyLinkedListNode* cloneList(SinglyLinkedListNode *head) {
if(head == NULL) return NULL;
SinglyLinkedListNode *result = (SinglyLinkedListNode *)malloc(sizeof(SinglyLinkedListNode));
result->data = head->data;
result->next = cloneList(head->next);
return result;
}
SinglyLinkedList* cloneFullList(SinglyLinkedList *list) {
if(list == NULL) return NULL;
SinglyLinkedList *result = (SinglyLinkedList *)malloc(sizeof(SinglyLinkedList));
result->size = list->size;
result->front = cloneList(list->front);
return result;
}
pushFront, popFront and calculateDistance functions are trivial and work correctly. (Can provide them if required, but I have tested them extensively, they work correctly)
The issue I am facing is that when I try to use this function in a loop, it breaks after a single iteration.
Example is
//templist is a normal linked list containing 11 nodes
SinglyLinkedListNode *ppp1 = templist->front;
SinglyLinkedListNode *ppp2 = templist->front;
int ctrin = 0, ctr=0;
while (ppp1 != NULL)
{
ctr++;
ppp2 = templist->front;
ctrin = 0;
while (ppp2 != NULL)
{
SinglyLinkedList* tp2 = createEmptyList();
SinglyLinkedList* np2 = createEmptyList();
ctrin++;
if (ppp1 == ppp2)
{
ppp2 = ppp2->next;
ctrin++;
}
shiftAndCluster(templist, tp2, np2, ppp1, ppp2, listType, 1);
templist = cloneFullList(list);
printf("(%d, %d)\n", ctr, ctrin);
ppp2 = ppp2->next;
}
iter++;
ppp1 = ppp1->next;
}
createEmptyList function just creates an empty list.
The output prints (1,2) indicating it does check for (1,1) and skip it and after shifting and clustering once, it breaks down. The incoming list is fine and I think there are issues with the logic of the function. Can someone please help?
May not be the only problem but when you do :
prev = curr1;
curr1 = curr1->next;
prev will always be different of curr1. So the test if (prev == curr1) if always false except if list->front is NULL
I'm trying to practice Linked Lists in C and I created a simple LL with an add function that takes a position index and inserts the data at that position.
I keep getting an infinite loop when trying to add to the beginning of my list using the add_beg, which just calls the add_at function with position 0 (add(0, data)) function. I can't seem to find the reason why this is happening. I need another set of eyes. Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int _data;
struct node_t *_next;
} node_t;
node_t *_head = NULL;
void add_at(int pos, int data) {
node_t *node = malloc(1 * sizeof(node_t));
node->_data = data;
node->_next = NULL;
// insert if empty
if (_head == NULL) {
_head = node;
}
else {
int index = 0;
node_t *prev = NULL;
node_t *curr = _head;
while (curr != NULL && index != pos) {
prev = curr;
curr = curr->_next;
index++;
}
// insert beginning
if (index == 0) {
_head = node;
node->_next = _head;
}
// insert end
else if (index != 0 && curr == NULL) {
prev->_next = node;
}
// insert middle
else {
prev->_next = node;
node->_next = curr;
}
}
}
void add_beg(int data) {
add_at(0, data);
}
void add_end(int data) {
add_at(-1, data);
}
void dump() {
if (_head != NULL) {
node_t *curr = _head;
while (curr != NULL) {
if (curr->_next != NULL) {
printf("%d -> ", curr->_data);
}
else {
printf("%d", curr->_data);
}
curr = curr->_next;
}
printf("\n");
}
else {
printf("The list is empty\n");
}
}
int main() {
add_beg(6);
add_at(1, 1);
add_at(2, 3);
add_at(3, 9);
add_at(4, 8);
add_at(5, 5);
add_at(7, 2);
add_at(8, 4);
add_beg(9); // commenting this out prevents the infinite loop
dump();
return 0;
}
The error is in this section:
if (index == 0) {
_head = node;
node->_next = _head;
}
That second command sets node->_next to head. However, the line before set _head to node. Therefore, you just set node->_next to node, creating the infinite loop.
You need to reverse the order of those two statements.
if (index == 0) {
_head = node;
node->_next = _head;
}
here you set _head as node but after next node at _head then when your doing while loop you had already broke your linked list.
Fix :
first set the _head as node->_next then set _head as node
My C/C++ linked-list remove function does not remove an element from the list. Here follows some of my code;
struct listIntElement {
struct listIntElement *next;
int data;
};
typedef struct listIntElement ListIntElement;
ListIntElement *head = NULL;
/*
Inserts a new element infront of the list.
*/
bool insert(ListIntElement **head, int data) {
// Allocate memory for new element. The cast is needed here as we are using a C++ compiler.
ListIntElement *newElement = (ListIntElement *) malloc(sizeof(ListIntElement));
// Check if memory allocation was succesfull.
if (newElement == NULL)
return false;
// Set the data for the new element of the list.
newElement->data = data;
// Keep track of the new head of the list.
newElement->next = *head;
*head = newElement;
return true;
}
/*
Deleting an element in the list.
*/
bool remove(ListIntElement **head, ListIntElement *elementToDelete) {
ListIntElement *element = *head;
// Check for NULL pointers.
if (head == NULL || *head == NULL || elementToDelete == NULL)
return false;
// Special case for the head.
if (elementToDelete == *head) {
*head = element->next;
free(elementToDelete);
return true;
}
// Traversal of the list to find the element to remove.
while (element != NULL) {
if (element->next == elementToDelete) {
// Relink the list so that it does not include the element to be deleted.
element->next = elementToDelete->next;
free(elementToDelete);
return true;
}
element = element->next;
}
// elementToDelete was not found.
return false;
}
/*
Finding an element in the list.
*/
ListIntElement find(ListIntElement **head, int data) {
// Take care of the head as we don't want to use the head
// in the traversal operation.
ListIntElement *element = *head;
while (element != NULL && element->data != data) {
element = element->next;
}
return *element;
}
/*
Displaying the list.
*/
void displayList(ListIntElement **head) {
ListIntElement *element = *head;
// Check if list is empty.
if (head == NULL | *head == NULL) {
printf("List is empty\n");
}
while (element != NULL) {
printf("%d --> ", element->data);
element = element->next;
}
printf("NULL");
printf("\n");
}
Here is my test code;
/*
* Testing a linked list.
*/
ListIntElement found;
printf("Linked list test\n");
insert(&head,0);
insert(&head, 1);
insert(&head, 2);
insert(&head, 3);
insert(&head, 4);
insert(&head, 5);
displayList(&head);
printf("size is: %d\n", size(&head));
found = find(&head, 5);
printf("This was found: %d\n", found.data);
remove(&head,&found);
displayList(&head);
I have found this section to be the section where things go wrong in the remove function;
// Special case for the head.
if (elementToDelete == *head) {
*head = element->next;
free(elementToDelete);
return true;
}
Take notice that I am using MS Visual Studio 2015 to write C code and using a C++ compiler.
From find function, you were returning a copy, and not the address itself, so your changes were not reflected in the calling function. Fixed it.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define true 1
#define false 0
struct listIntElement {
struct listIntElement *next;
int data;
};
typedef struct listIntElement ListIntElement;
ListIntElement *head = NULL;
/*
Inserts a new element infront of the list.
*/
bool insert(ListIntElement **head, int data) {
// Allocate memory for new element. The cast is needed here as we are using a C++ compiler.
ListIntElement *newElement = (ListIntElement *) malloc(sizeof(ListIntElement));
// Check if memory allocation was succesfull.
if (newElement == NULL)
return false;
// Set the data for the new element of the list.
newElement->data = data;
// Keep track of the new head of the list.
newElement->next = *head;
*head = newElement;
return true;
}
/*
Deleting an element in the list.
*/
bool removeElement (ListIntElement **head, ListIntElement *elementToDelete) {
ListIntElement *element = *head;
// Check for NULL pointers.
if (head == NULL || *head == NULL || elementToDelete == NULL)
return false;
// Special case for the head.
if (elementToDelete == *head) {
*head = element->next;
free(elementToDelete);
return true;
}
// Traversal of the list to find the element to remove.
while (element != NULL) {
if (element->next == elementToDelete) {
// Relink the list so that it does not include the element to be deleted.
element->next = elementToDelete->next;
free(elementToDelete);
return true;
}
element = element->next;
}
// elementToDelete was not found.
return false;
}
/*
Finding an element in the list.
*/
ListIntElement *find(ListIntElement **head, int data) {
// Take care of the head as we don't want to use the head
// in the traversal operation.
ListIntElement *element = *head;
while (element != NULL && element->data != data) {
element = element->next;
}
return element;
}
/*
Displaying the list.
*/
void displayList(ListIntElement **head) {
ListIntElement *element = *head;
// Check if list is empty.
if (head == NULL | *head == NULL) {
printf("List is empty\n");
}
while (element != NULL) {
printf("%d --> ", element->data);
element = element->next;
}
printf("NULL");
printf("\n");
}
int main () {
ListIntElement *found;
printf("Linked list test\n");
insert(&head,0);
insert(&head, 1);
insert(&head, 2);
insert(&head, 3);
insert(&head, 4);
insert(&head, 5);
displayList(&head);
printf("size is: %d\n", sizeof(&head));
found = find(&head, 5);
printf("This was found: %d\n", found->data);
removeElement(&head,found);
displayList(&head);
}
Output:
Linked list test
5 --> 4 --> 3 --> 2 --> 1 --> 0 --> NULL
size is: 4
This was found: 5
4 --> 3 --> 2 --> 1 --> 0 --> NULL
After spending more than 10 hrs, the following code is developed:
struct stockRecord* temp = NULL;
struct stockRecord* head = NULL;
struct stockRecord* prevptr = NULL;
struct stockRecord* recurfun(struct stockRecord* list) {
temp = list;
if (head == NULL) head = temp;
if (temp == NULL) {
return head;
} else {
/*first node*/
if (prevptr == NULL) {
if (strstr(temp->name, "ABC-") != NULL) {
temp = temp->next;
head = temp;
prevptr = head;
}
}
/*last node*/
if (temp->next == NULL) {
if (strstr(temp->name, "ABC-") != NULL) {
prevptr->next = NULL;
}
return head;
}
/*middle node*/
if (strstr(temp->name, "ABC-") != NULL) {
prevptr->next = temp->next;
} else {
if (prevptr != NULL) {
prevptr = temp;
} else {
prevptr = head;
}
}
return recurfun(temp->next);
}
The problem is, when first node and the second node also contains "ABC-", the function only remove the first node, the second node still can't be removed.
What's the problems of my code?
Suppose you start out with 1->2->3
After you remove the first node, you set prevptr, head, and temp to all point to 2.
Then at the end of the function you recursively call it on temp->next which points to 3.
The result is that you are skipping the second node when you remove the first.