I cannot figure out why my code to sort the elements of a list does not work, it sort the first 5 element of the list and then just stop. I know it may be a stupid problem but I checked the loop a lot of time and can't understand why it reach the exit before the end of the list.
typedef enum { NOTORD=0, TIME=1, POSITION=2 } ord_t;
typedef struct elem {
double position;
double time;
flag_t flag;
struct elem * next;
} elem_t;
typedef struct {
elem_t * head;
int nelem;
ord_t ord;
} lista_t;
void set_ordinata_time (lista_t * l)
{
if (l->ord!=TIME) {
elem_t * aux, *corr, *succ;
int scambio;
corr=l->head;
succ=l->head->next;
aux=malloc(sizeof(elem_t));
scambio=1;
while(scambio==1)
{
corr=l->head;
succ=l->head->next;
scambio=0;
while(succ != NULL)
{
if (corr->time > succ->time)
{
aux=corr;
aux->next=succ->next;
corr=succ;
succ=aux;
corr->next=succ;
scambio=1;
}
corr=succ; succ=succ->next;
}
}
l->ord=TIME;
}
}
When you are swapping, if corr is l->head then you need to reset l->head to succ. If you don't, then the next time through the loop, the sort will start from wherever l->head ended up after the first pass.
Also, you will be losing (and leaking) part of the list.
EDIT: More from comments
It applies generally to corr's previous element (it needs to be reset to succ when swapping)
There's no need to allocate an instance of elem_t. When swapping elements, there's an issue if one of the elements is the first one in the list, or if the elements are adjacent elements. Using pointers to pointer to element can reduce the number of if statements. A pointer to pointer could be the address of head or the address of a nodes next pointer.
To implement a swap, first swap whatever points to the two nodes (could be head or a node next pointer), then swap the two nodes next pointers. This will take care of the adjacent versus not adjacent node issue.
Related
This is my program to sort a linked list by Bubble sort. When I use while it is OK, but when I use for loop it have an infinite loop so my program is stop unexpectedly. On the other hand, for the first swap of first and second element, I change pointer head point to the second but maybe it doesn't work for the whole program.
For example,
Ex1:
Input : 3,2,4,1,5
Output: 2,3,4,5
Ex2:
Input: 4,3,2,1,5
Output:3,4,5
Ex3:
Input: 3,2,1
Output: 2,3
I think that it just change the address the head pointer point to for the first time, so head is point to 2 in Ex1, 3 in Ex2 and 2 in Ex3.
void Swap(Node *p1, Node *p2)
{
Node *t;
t=p2->next;
p2->next=p1;
p1->next=t;
}
Node *BubbleSort(Node *head,int n) //pass the address of the first element in linked list and the linked list size
{
Node *tmp=head;
int swap=1;
for(int i=0;i<n-1;i++)
{
tmp=a; swap=0;
for(int j=0;j<n-1;j++)
{
if((tmp->data)>(tmp->next->data))
{
if(j==0) //if this is the first and second element I will change the address of the pointer
a=tmp->next;
Swap(tmp,tmp->next);
swap=1;
}
else tmp=tmp->next; //If the element I focus on is not greater than its folowing I will move the tmp pointer to the next.
}
if(swap==0)
return head;
}
return head;
}
int main()
{
Node*head;
//Assume I have a linked list with n elements
head=BubbleSort(head,n);
}
I searched for an other way in GeekforGeek but I still want to know why my code doesn't work. I have think for almost a long day. Please help me !
The Swap function is off by one. Therefore, in the innermost loop body you need to Swap(tmp->prev, tmp) instead of Swap(tmp, tmp->next).
You need to compare and swap the same elements, not compare the current and next element but swap the next and 2nd next element.
if( (tmp->data) > (tmp->next->data) ), then tmp->prev->next should point to tmp->next and tmp->next->next should point to tmp.
However, there is one thing to take care of: As you Swap(tmp->prev, tmp) you need to start one element further, too. This is also clear from the fact that the head points to the first element but does not contain any data. first->prev should point to the head, the head should be rw.
It's possible to let the top level code maintain the head but it's better if the ll code maintains it's own head.
I'm trying to create a linked list without using structures in C.
I want to be able to store an int variable on every node and a pointer to the next node, add unlimited numbers to the list, remove the first item, print all of the elements, etc.
I was thinking that every node of type int** should have 2 pointers of type int*.
the first one will point to an int address and the second will point to NULL.
Then, if I like to add a number to the list, I'll use the last pointer to point to a new allocated node of type int** and so on.
I'm having trouble writing the proper code for this though, and can't seem to reach to the actual int values. See the image below:
You can achieve this by allocating two uintptr_t each time: the first allocated memory space will be responsible for storing the value of the integer and the second one will be pointing to the next memory location.
uintptr_t nodeFirst = malloc(2 * sizeof(uintptr_t));
...
...
uintptr_t nodeNext = malloc(2 * sizeof(uintptr_t));
....
....
*nodeFirst = someIntValue;
*(nodeFirst + 1) = nodeNext;
...
The fact is, my solution above is still using the struct analogy, but w/o the struct keyword.
Here is a complete solution of a LinkedList managed as int ** pointers.
Step 1 - the addNode() function to add one node to the int **head.
int **addNode(int **head, int ival)
{
int **node = malloc(2 * sizeof(int *));
// don't forget to alloc memory to store the int value
node[0] = malloc(sizeof(int));
*(node[0]) = ival;
// next is pointing to NULL
node[1] = NULL;
if (head == NULL) {
// first node to be added
head = node;
}
else {
int **temp;
temp = head;
// temp[1] is the next
while (temp[1]!=NULL) {
// cast needed to go to the next node
temp = (int **)temp[1];
}
// cast needed to store the next node
temp[1] = (int *)node;
}
return (head);
}
Step 2 - a function display() to explore the current linkedlist.
void display(int **head)
{
int **temp;
int i = 0;
temp = head;
printf("display:\n");
while (temp!=NULL) {
// temp[0] is pointing to the ivalue
printf("node[%d]=%d\n",i++,*(temp[0]));
temp = (int **)temp[1];
}
printf("\n");
}
Step 3 - the popNode() function to remove the first node.
int **popNode(int **head)
{
int **temp;
if (head!=NULL) {
temp = (int **)head[1];
// don't forget to free ivalue
free(head[0]);
// then free the next pointer
free(head[1]);
head = temp;
}
return (head);
}
Step 4 - then an example of main() function using the linkedlist.
int main()
{
int **head = NULL;
head = addNode(head,111);
head = addNode(head,222);
head = addNode(head,333);
display(head);
// display:
// node[0]=111
// node[1]=222
// node[2]=333
head = popNode(head);
display(head);
// display:
// node[0]=222
// node[1]=333
while ((head = popNode(head))!=NULL);
display(head);
// display:
return (0);
}
Allocate two arrays, both of which are stored as pointers. In C, they can be the pointers you get back from calloc(). The first holds your node data. We can call it nodes. The second is an array of pointers (or integral offsets). We can call it nexts. Whenever you update the list, update nodes so that each nexts[i] links to the next node after the one that contains nodes[i], or an invalid value such as NULL or -1 if it is the tail. For a double-linked list, you’d need befores or to use the XOR trick. You’ll need a head pointer and some kind of indicator of which elements in your pool are unallocated, which could be something simple like a first free index, or something more complicated like a bitfield.
You would still need to wrap all this in a structure to get more than one linked list in your program, but that does give you one linked list using no data structure other than pointers.
This challenge is crazy, but a structure of arrays isn’t, and you might see a graph or a list of vertices stored in a somewhat similar way. You can allocate or deallocate your node pool all at once instead of in small chunks, it could be more efficient to use 32-bit offsets instead of 64-bit next pointers, and contiguous storage gets you locality of reference.
I have to print a list of a set in c using linked lists (hence pointers). However,when I delete the first element of the list and try to print the list, it just displays a lot of addresses under each other. Any suggestions of what the problem might be? Thanks!
Delete function:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
If the list pointer is the same as a pointer to the first element then the list pointer is no longer valid when you free the first element.
There are two solutions to this problem:
Let all your list methods take a pointer to the list so they can update it when neccesary. The problem with this approach is that if you have a copy of the pointer in another variable then that pointer gets invalidated too.
Don't let your list pointer point to the first element. Let it point to a pointer to the first element.
Sample Code:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;
This normally happens when you delete a pointer (actually a piece of the memory) which doesn't belong to you. Double-check your function to make sure you're not freeing the same pointer you already freed, or freeing a pointer you didn't create with "malloc".
Warning: This answer contains inferred code.
A typical linked list in C looks a little something like this:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
In order to correctly delete the first element from the list, the following sequence needs to take place:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
The order of operations here is significant! Attempting to move the head without first freeing the old value will lead to a memory leak; and freeing the old head without first obtaining the correct value for the new head creates undefined behaviour.
Addendum: Occasionally, the _list portion of the above code will be omitted altogether, leaving lists and list nodes as the same thing; but from the symptoms you are describing, I'm guessing this is probably not the case here.
In such a situation, however, the steps remain, essentially, the same, but without the aList-> bit.
Edit:
Now that I see your code, I can give you a more complete answer.
One of the key problems in your code is that it's all over the place. There is, however, one line in here that's particularly bad:
*src = *currElement->next;
This does not work, and is what is causing your crash.
In your case, the solution is either to wrap the linked list in some manner of container, like the struct _list construct above; or to rework your existing code to accept a pointer to a pointer to a set element, so that you can pass pointers to set elements (which is what you want to do) back.
In terms of performance, the two solutions are likely as close so as makes no odds, but using a wrapping list structure helps communicate intent. It also helps prevent other pointers to the list from becoming garbled as a result of head deletions, so there's that.
I wrote the following function which returns the middle element of a linked list, which uses the double pointer method
struct node
{
int data;
struct node *next;
}*start;
void middleelement()
{
struct node *x=start,*y=start;
int n=0;
if(start==NULL)
{
printf("\nThere are no elments in the list");
}
else
{
while((x->next)!=NULL)
{
x=x->next->next;
y=y->next;
n++;
}
printf("\nMiddle element is %d",y->data);
}
}
However, whenever I run the functions, the Windows explorer stops working
What is the flaw in the code?
Is there any better algorithm than this to find the middle element?
If the number of entries is odd, your x will end up being NULL, so when the next loop iteration dreferences it, your program is going to crash. You should modify your condition to account for that:
while(x && x->next) {
...
}
Comparing with NULL is optional in C, so you can skip the != NULL to shorten the condition.
Of course passing the start parameter through a global variable is unorthodox, to say the least. It would be much better to pass it as a regular function parameter.
I'm having trouble reversing my doublely linked deque list (with only a back sentinel) in C, I'm approaching it by switching the pointers and here is the code I have so far:
/* Reverse the deque
param: q pointer to the deque
pre: q is not null and q is not empty
post: the deque is reversed
*/
/* reverseCirListDeque */
void reverseCirListDeque(struct cirListDeque *q)
{
struct DLink *back = q->backSentinel;
struct DLink *second = q->backSentinel->prev;
struct DLink *third = q->backSentinel->next;
while (second != q->backSentinel->next){
back->next = second;
third = back->prev;
back->next->prev = back;
back = second;
second = third;
}
}
But it doesn't seem to work, I've been testing it with a deque that looks like this: 1, 2, 3
The output is: 3 and this process seems to mess up the actual value of the numbers. ie. 2 becomes 2.90085e-309... I think the pointer switching is messed up but I cannot find the problem. And even though it doesn't mean my code is correct; it compiles fine.
Linked structures like deques lend themselves readily to recursion, so I tend to favor a recursive style when dealing with linked structures. This also allows us to write it incrementally so that we can test each function easily. Looping as your function does has many downsides: you can easily introduce fencepost errors and it tends toward large functions that are confusing.
First, you've decided to do this by swapping the pointers, right? So write a function to swap pointers:
void swapCirListDequePointers(
struct cirListDeque** left,
struct cirListDeque** right)
{
struct cirListDeque* temp = *left;
*left = *right;
*right = temp;
}
Now, write a function that reverses the pointers in a single node:
void swapPointersInCirListDeque(struct cirListDeque* q)
{
swapCirListDequePointers(&(q->prev),&(q->next));
}
Now, put it together recursively:
void reverseCirListDeque(struct cirListDeque* q)
{
if(q == q->backSentinel)
return;
swapPointersInCirListDeque(q);
// Leave this call in tail position so that compiler can optimize it
reverseCirListDeque(q->prev); // Tricky; this used to be q->next
}
I'm not sure exactly how your struct is designed; my function assumes that your deque is circular and that you'll be calling this on the sentinel.
EDIT: If your deque isn't circular, you'll want to call swapPointersInCirListDeque(q) on the sentinel as well, so move swapPointersInCirListDeque(q) before the if statement.
If you plan to use the backSentinel after this, you should change that also, since it's now the front of the list. If you have a frontSentinel, you can just add swapCirListDequePointers(&(q->frontSentinel),&(q->backSentinel)); to swapPointersInCirListDeque. Otherwise, you'll have to pass in the first node along with q and set q->backSentinel to that.
If it's a doubly linked list, you shouldn't need to change any pointers at all. Just swap over the payloads:
pointer1 = first
pointer2 = last
while pointer1 != pointer2 and pointer2->next != pointer1:
temp = pointer1->payload
pointer1->payload = pointer2->payload
pointer2->payload = temp
pointer1 = pointer1->next
pointer2 = pointer2->prev
If by back sentinel you mean the last pointer (as in no first pointer is available), then you need to step backwards throw the deque to find it. It's hard to believe however that this would be the case since it would be a fairly inefficient deque (which is supposed to be a double ended queue).
You've been given a couple of suggestions already; here's another possibility:
// Assumes a node something like:
typedef struct node {
struct node *next, *prev;
int data;
} node;
and also assumes a couple of variables (globals for the moment) named head and tail that point to the head and tail of the deque, respectively.
void reverse() {
node *pos = head;
node *temp = pos->next;
head = tail;
tail = pos;
while (pos != NULL) {
node *t = pos->prev;
pos->prev = pos->next;
pos->next = t;
pos = temp;
if (temp)
temp = temp->next;
}
}
At least for the moment, this does not assume any sentinels -- just NULL pointers to signal the ends of the list.
If you're just storing ints in the deque, Paxdiablo's suggestion is a good one (except that creating a doubly-linked node to hold only an int is a massive waste). Assuming that in reality you were storing something large enough for doubly-linked nodes to make sense, you'd also prefer to avoid moving that data around any more than necessary, at least as a general rule.