This is my code:
#include <stdlib.h>
typedef struct _node {
int data;
struct _node* next;
} llnode;
llnode* llgetindex(llnode** header, int index){
if(*header == NULL) return NULL;
llnode* i = *header;
llnode* j = *header;
if(index < 0){
// negative indexes
while(index < 0){
if(i == NULL) return NULL;
i = i->next;
index++;
}
while(i != NULL){
i = i->next;
j = j->next;
}
return j;
} else {
//positive indexes
while(index > 0){
if(i == NULL) return NULL;
i=i->next;
index--;
}
return i;
}
}
llnode* push(llnode** header, int data){
if(*header == NULL) {
llnode* item = malloc(sizeof(llnode));
item->data = data;
item->next = NULL;
*header = item;
return item;
} else {
llnode* item = llgetindex(header, (-1));
item->next = malloc(sizeof(llnode));
item->next->data = data;
item->next->next = NULL;
return item->next;
}
}
llnode* pop(llnode** header){
if(*header == NULL) return NULL;
llnode* last = NULL;
// if list is one item long
if((*header)->next == NULL){
last = *header;
*header = NULL;
} else {
llnode* blast = llgetindex(header,(-2));
printf("[0]%lli\n",*header);
printf("[1]%lli\n",(*header)->next);
last = blast->next;
blast->next = NULL;
}
return last;
}
I've traced the problem to the function llgetindex; it somehow is overwriting the pointer to the first element of the list and changing it to what llgetindex should return when given a negative index, but i don't get how.
The strangest thing is that calling push works fine, pop doesn't and calling llgetindex directly also destroys the list.
If you can explain why it happens i would be happy.
To reproduce the problem:
create a llnode** pointer and call push function a few times to populate the list, after call either pop or llgetindex using a negative index and check the list, now the first node of the list should now be either the last if you called pop, or the element indexed by the negative index given to llgetindex.
gcc (Debian 10.2.1-6) 10.2.1 20210110
Related
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
#include <stdio.h>
#include <malloc.h>
struct el {
int info;
struct el* next;
};
struct el* create_el(struct el* Li)
{
int num;
printf("\n\nInsert number:\n\n");
scanf("%d", &num);
Li = (struct el*)malloc(sizeof(struct el));
if (Li != NULL) {
Li->info = num;
Li->next = NULL;
}
return (Li);
}
struct el* push(struct el* L, struct el* e)
{ //inserts the elements from the head of the list
if (L == NULL)
return (e);
else {
e->next = L;
L = e;
return (L);
}
}
void visualize(struct el* primo)
{
printf("\n\nList-->");
while (primo->next != NULL) {
printf("%d", primo->info);
printf("-->");
primo = primo->next;
}
if (primo->next == NULL)
printf("%d-->NULL", primo->info);
}
struct el* cancel(struct el** P, int val)
{ //delete element
struct el* prec = NULL;
struct el* curr = (*P);
if (P == NULL) //case empty list
return NULL;
else if (prec == NULL) {
if (curr->info == val) { //case 2 : if the element is the head
(*P)->next = curr->next;
free(curr);
curr = NULL;
}
}
else {
while ((curr != NULL) && (curr->info != val)) {
prec = curr;
curr = curr->next;
}
if (curr->next == NULL && curr->info == val) { // case 3: the elemnt is the last one
prec->next = NULL;
free(curr);
curr = NULL;
return (prec);
}
else {
if (curr->info == val) { //other cases
prec->next = curr->next;
free(curr);
curr = NULL;
return (prec);
}
}
}
}
int main()
{
struct el* head = NULL;
struct el* element;
struct el* list = NULL;
int i, n;
int elem;
printf("Insert the number of elements for the list:\n\n");
scanf("%d", &n);
for (i = 0; i <= n; i++) {
element = create_el(head);
if (element != NULL) {
list = push(list, element);
}
}
visualize(list);
printf("\n\nInsert the element that you want to cancel:");
elem = scanf("%d", &elem);
cancel(&list, elem);
visualize(list);
}
All I've wanted to do was delete an element from a listr, but after all the procediment the list is printed without any modification.
Can anyone see whats wrong in the function cancel(which is meant to delete an element by including any possible position of it)?
In your function cancel, P is definitely not NULL (assuming OS has assigned it an address initially).
prec is NULL the before execution enters if loop.
So, execution executes the line
if(curr->info==val)
Now, if the value, val, you have provided doesn't match curr->info then execution exits the function without deleting any node.
I am using a struct like this
struct infoM {
char* direction;
int key;
};
typedef struct nodeM{
struct infoM nodeInfo;
struct nodeM *next;
struct nodeM *prev;
} node;
typedef node list;
I have one function that returns the wanted node by a specific field
node * search(list *l, char* direction) {}
And this is my function to remove elements from the list
int delete(list *l, char* direction) {
node *tmp = search(l, direction);
if (tmp != NULL) {
node *ant = tmp->prev;
node *seg = tmp->next;
if (seg != NULL) {
if (ant != NULL) {
ant->next = seg;
seg->prev = ant;
free(tmp);
return 1;
} else { //prev null
seg->prev = NULL;
*l = *seg;
tmp = NULL;
free(tmp);
return 1;
}
} else { //next null
if (ant == NULL) {
l->nodeInfo.key = somevalue;
l->next = NULL;
l->prev = NULL;
return 1;
} else {
printf("Here is the problem\n");
ant->next = NULL;
free(tmp);
return 1;
}
}
} else { //tmp nulo
perror("Error delete : node null\n");
return 0;
}
}
If I have 4 elements in the list, 1234 and I delete first first element everything is okay and returns 234. If I delete the last element it returns 23 seems to work great. But if I try to delete the last element now the function does nothing despite being the same case that when it is 234 and I don't understand why. The list is not being updated.
In the main I am using the list like this :
list a;
delete(&a, "whatever");
What am I doing wrong ?
This is the code for search
node * createnode(){
node *tmp = (node *) malloc (sizeof(node));
return tmp;
}
node * search(list *l, char* direction) {
node *tmp = createnode();
if (l->nodeInfo.key == 777) {
perror("Error search: empty list\n");
return NULL;
}
tmp=l;
while((strcmp(direction, tmp->nodeInfo.direction) !=0) && (tmp->next != NULL)) {
tmp = tmp->next;
}
if (strcmp(direction, tmp->nodeInfo.direction) == 0) {
return tmp;
} else {
perror("Error search: element not found\n");
return NULL;
}
}
I am trying to code very basic sorting method for linked lists. I am getting unhandled exception. What is the mistake i am making? Here is my code:-
struct LinkedNode// structure for linked list
{
int data;
struct LinkedNode *next;
}*start = NULL;
following function creates a linked list
void CreateLinkedList()
{
LinkedNode *newNode, *current;
printf("enter 5 numbers to create linked list\n");
for(int i=0; i<5; i++)
{
newNode = (struct LinkedNode *)malloc(sizeof(LinkedNode));
scanf("%d", &newNode->data);
newNode->next = NULL;
if(start == NULL)
{
start = newNode;
current = newNode;
}
else
{
current->next = newNode;
current = newNode;
}
}
}
following function is used for sorting the linked list nodes
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
temp = node->next;//temp node to hold node data and next link
while(node != NULL && node->next != NULL)
{
for(int j=0; j<5; j++)//value 5 because I am taking only 5 nodes
{
if(node->data > temp->data)//swap node data
{
tempvar = node->data;
node->data = temp->data;
temp->data = tempvar;
}
temp = temp->next;
}
node = node->next;
}
}
Try This code
void SortLinkedList()
{
struct LinkedNode *node=NULL, *temp = NULL;
int tempvar;//temp variable to store node data
node = start;
//temp = node;//temp node to hold node data and next link
while(node != NULL)
{
temp=node;
while (temp->next !=NULL)//travel till the second last element
{
if(temp->data > temp->next->data)// compare the data of the nodes
{
tempvar = temp->data;
temp->data = temp->next->data;// swap the data
temp->next->data = tempvar;
}
temp = temp->next; // move to the next element
}
node = node->next; // move to the next node
}
}
1 - outer while loop is use for the total number of pass that will require to sort the linked list..
2- In second while loop we are actually comparing the data of the nodes that we want to sort
Instead of implementing your own sort, you can just use qsort. Of course, qsort requires an array, but that is easy enough to create.
In this case, you know that the list has 5 members. But, if you didn't know, you could just count them.
int size_of_list = 0;
struct LinkedNode *p;
for (p = start; p != NULL; p = p->next) ++size_of_list;
if (size_of_list == 0) {
// Nothing to do
return;
}
Now you can create your array;
struct LinkedNode *arr[size_of_list + 1], **arrp = arr;
for (p = start; p != NULL; p = p->next) *arrp++ = p;
*arrp = NULL;
Then, use qsort on arr. There are lots of examples, but the trick is writing an appropriate comparison function.
int cmp_LinkedNode(const void *a, const void *b) {
const struct LinkedNode * const *aa = a;
const struct LinkedNode * const *bb = b;
return ((*aa)->data > (*bb)->data) - ((*aa)->data < (*bb)->data);
}
//...
qsort(arr, size_of_list, sizeof(*arr), cmp_LinkedNode);
And then, rewire the list into the sorted order.
for (int i = 0; i < size_of_list; ++i) arr[i]->next = arr[i+1];
start = arr[0];
yeah sorting a linked list using nodes/links is a pretty hard job. Spend hours doing it myself but since i have done it why not help others..
What you need to do is simply find the minimum value in your list. Swap it with the head node and the recur for head->next.
The code for sort is only of 3 to 4 lines if you have FindMin() and Swap() functions made..
here is the complete code for sort(),swap()and findmin().
void sort(node **start)
{
if (((*start)->next == NULL) || (*start == NULL))
{
return;
}
node *min = findmin(*start);
swap(*start, min, start);
sort(&((*start)->next));
}
void swap(node *p1, node *p2, node **start)
{
node *p1pre = NULL;
node *p1curr = *start;
while (p1curr!=p1)
{
p1pre = p1curr;
p1curr = p1curr->next;
}
node *p2pre = NULL;
node *p2curr = *start;
while (p2curr != p2)
{
p2pre = p2curr;
p2curr = p2curr->next;
}
if (p1pre != NULL)
{
p1pre->next = p2curr;
}
else
{
*start = p2curr;
}
if (p2pre != NULL)
{
p2pre->next = p1curr;
}
else
{
*start = p1curr;
}
node *temp = p2curr->next;
p2curr->next = p1curr->next;
p1curr->next = temp;
}
node* findmin(node *start)
{
int flag = 0;
if (start == NULL)
{
cout << "list is empty" << endl;
}
else
{
node *curr = start->next;
node *min = start;
while (curr->next != NULL)
{
if (min->value > curr->value)
{
min = curr;
flag++;
}
curr = curr->next;
}
if ((curr->next == NULL) && (min->value > curr->value))
{
min = curr;
flag++;
}
if (flag > 0)
{
return min;
}
}
}