C.....Shufling values of linked list - c

I am writing a war cards game. I need to shufle first few elements of players hand (linked list).
That`s what i have:
void tasowanie(llist_t** head, int warsize) {
llist_t** temp = head;
Card_t temp_card;
int random;
while (warsize > 0) {
random = rand() % warsize;
for (int j = 0; j < random; j++)
if ((*temp)!=NULL && (*temp)->next != NULL)
*temp = (*temp)->next;
temp_card = (*head)->card;
(*head)->card = (*temp)->card;
(*temp)->card = temp_card;
*head = (*head)->next;
*temp = *head;
warsize--;
}
}
The problem is that I am losing elements of this list.
I was thinking about puting these elements into array, then shufling it and puting it back to the list, although I imagine there has to be more elegant solution.

You should not be writing to *temp, as this is a pointer to the real list next pointer.
The same applies to moving head: unless you intend to update the list you should not be touching *head.
Instead, when you want to update temp you should set it with temp = &((*temp)->next), and reset with temp=head.
void tasowanie(llist_t** head, int warsize) {
llist_t** temp = head;
Card_t temp_card;
int random;
while (warsize > 0) {
random = rand() % warsize;
for (int j = 0; j < random; j++)
if ((*temp)!=NULL && (*temp)->next != NULL)
temp = &((*temp)->next);
temp_card = (*head)->card;
(*head)->card = (*temp)->card;
(*temp)->card = temp_card;
head = &((*head)->next);
temp = head;
warsize--;
}
}

Related

Why am I losing a node when shuffling a linked list?

I have been working on a project. Part of the project needs a shuffled linked list. This function is an implementation of the fisher-yates shuffling algorithm. It puts the linked list into an array. Then it shuffles it. Then relinks it.
After some testing I have found that sometimes when I shuffle a linked list, I lose a node somewhere. I have done some testing with ubsan and asan. They both show nothing. I used to have a issue with this function causing a segfault later on. The segfault was causing by not relinking the linked list correctly. More specifically the last node before shuffling in the linked list was not relinked correctly. I fixed that somewhat by making the list circular before shuffling it.
Here is the code used for shuffling along with the swap and relink functions:
linked_node* shuffle(linked_node* head) {
int count = 0;
linked_node* count_head = head;
while (count_head != NULL) {
count++;
count_head = count_head->next;
}
#ifdef DEBUG
fprintf(stderr, "count: %i\r\n", count);
#endif
linked_node** array = malloc(count * sizeof(linked_node*));
int i = 0;
linked_node* add_head = head;
for (i = 0; i < count; i++) {
array[i] = add_head;
add_head = add_head->next;
}
//made circluar to prevent segfault with the last node
array[count - 1]->next = head;
srand48(time(NULL));
for (int j = count - 1; j > 0; j--) {
int random = lrand48() % (j+1);
array_swap(&array[j], &array[random]);
}
for (int k = 0; k > count - 1; k++) {
relink(array[k], array[k + 1]);
}
linked_node* new_head = array[0];
//made circular for ease of use later
array[count - 1]->next = new_head;
free(array);
return new_head;
}
static inline void relink(linked_node* prev, linked_node* next) {
if (prev != NULL && next != NULL) {
prev->next = next;
}
}
void array_swap(linked_node** a, linked_node** b) {
linked_node* temp = *a;
*a = *b;
*b = temp;
}
There is a typo in this for loop
for (int k = 0; k > count - 1; k++) {
^^^^^^^^^^^^^
relink(array[k], array[k + 1]);
}
It seems you mean
for (int k = 0; k < count - 1; k++) {
^^^^^^^^^^^^^
relink(array[k], array[k + 1]);
}
Also this statement
//made circluar to prevent segfault with the last node
array[count - 1]->next = head;
is redundant and actually does not have an effect. Remove it.
This statement
//made circular for ease of use later
array[count - 1]->next = new_head;
could be substituted for this statement
array[count - 1]->next = NULL;

Sum of all elements of a list in C

I need to get the sum of a list that only contains doubles.
For some reason that doesn't work, though:
double sum(DoubleList* list) {
DoubleNode *next = NULL;
double sum = 0;
for (DoubleNode *n = list->first; n != NULL; n = next) {
sum += n->value;
}
return sum;
}
You should fix your loop as follows.
double sum(DoubleList* list) {
double sum = 0;
for (DoubleNode *n = list->first; n != NULL; n = n->next) {
sum += n->value;
}
return sum;
}
The sample code above assumes DoubleNode has an attribute named next and is of type DoubleNode*, that stores the pointer to the next element.
You need to ensure you get the next element in your loop. I am guessing that the next pointer is n->next:
for (DoubleNode *n = list->first; n != NULL; n = n->next) {
sum += n->value;
}
Change
for (DoubleNode *n = list->first; n != NULL; n = next)
to
for (DoubleNode *n = list->first; n != NULL; n = n->next)

Linked list of "random" values, program hangs

I'm trying to learn C a little bit and am dealing with linked lists right now. I have defined a linked list as:
struct data {
int xVal;
int yVal;
struct data *next;
};
What I want to do is insert num pairs of values into the linked list, but each pair must be unique.
void addToList(num) {
srand(time(NULL));
struct data *list = NULL;
list = malloc(sizeof(struct data));
struct data *q = list;
list->xVal = rand() % 100;
list->yVal = rand() % 100;
int j = 0;
while (j < num-1) {
q->next = malloc(sizeof(struct data));
q->next->xVal = rand() % 100;
q->next->yVal = rand() % 100;
if (unique(list, q->next->xVal, q->next->yVal)) {
q = q->next;
j++;
}
}
}
bool unique(struct data *list, int x, int y) {
struct data *q = list;
while (q->next != NULL) {
if (q->xVal = x && q->yVal == y) { return false; }
q = q->next;
}
return true;
}
What it does is it generates a random value 1-100 for both xVal and yVal, checks if that pair already exists in the list, and if not it inserts at the end. It compiles fine, but running the program makes it hang. I don't see any infinite loops here. I've tried with num equal to 2 and it still hangs.
Removing the check for unique values lets me fill and print the list, but I still run into an exception "Access violation reading location 0xCDCDCDD9.".
Problem
You have a logic error.
You add couple of values to the list using:
q->next->xVal = rand() % 100;
q->next->yVal = rand() % 100;
and then check whether they exist in the list. Of course they do. The return value from unique is always false. As a consequence, j never gets incremented and the list keeps growing despite j not being incremented.
Fix
Get the random numbers.
Check whether they are unique before adding them to the list.
Here's how I see it.
void addToList(num) {
srand(time(NULL));
struct data *list = NULL;
list = malloc(sizeof(struct data));
struct data *q = list;
list->xVal = rand() % 100;
list->yVal = rand() % 100;
int j = 0;
while (j < num-1) {
int x = rand() % 100;
int y = rand() % 100;
if ( unique(list, x, y) ) {
q->next = malloc(sizeof(struct data));
q->next->xVal = x;
q->next->yVal = y;
q->next->next = NULL; // Make sure the list has a clean end
q = q->next;
j++;
}
}
}
And ...
You also have a typo in unique.
if (q->xVal = x && q->yVal == y) { return false; }
should be:
if (q->xVal == x && q->yVal == y) { return false; }
// ^^ Need to compare, not assigh.

Swap kth position from start and end in a single traverse linked list

I have come across the following implementation for swapping the kth position from start and end in a linked list in single traverse.
node *list;
node *p, *q, *r;
p = q = r = list;
i = 1;
while(p != NULL)
{
if(i != k)
{
q = q->next;
i++;
}//q will eventually point to kth node from starting
if(i == k)
{
r = r->next
}//r will eventually point to kth node from end
p = p->next;
}
Swap q & r elements
But I feel it's not the right implementation, could anyone look at it and verify if it's correct?
If it's wrong, what changes would I have to make?
This question is majorly associated with finding right nodes and respective previous node.
Then essentially there are 2 cases when nodes are starting and ending node or they are intermediate nodes.
First adjust previous pointer to point swap targets and then swap next pointers of targets. That is all ... following is complete java code for reference ->
JAVA Code
public class SwapKthNodeTest {
public static void main(String[] args) {
Test10Node();
System.out.println();
Test2Node();
}
private static void Test2Node() {
Node head = Node.getNodeListHead(2);
Node.ToString(head);
int k = 1;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k = 2;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
}
public static void Test10Node(){
Node head = Node.getNodeListHead(10);
Node.ToString(head);
int k = 2;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=1;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=3;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=4;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
k=5;
head = Node.SwapKthNodeFromStartNEnd(head, k);
Node.ToString(head);
}
}
class Node {
int val;
Node next;
Node(int val, Node next) {
this.val = val;
this.next= next;
}
public static int length(Node head){
Node trav = head;
int count = 0;
while(trav != null){
count++;
trav = trav.next;
}
return count;
}
public static void ToString(Node head) {
// just print the list which we created
Node trav = head;
while(trav != null){
System.out.print(trav.val+" ");
trav = trav.next;
}
}
public static Node SwapKthNodeFromStartNEnd(Node head, int k) {
System.out.println();
int len = Node.length(head);
if( k > len) return head;
// would be the same thing just making it reverse
// to make process more cleaner
if( k == len) k = 1;
Node x = head, y = head, t = head;
Node xp = null, yp = null;
int i = 1;
while (i++ < k) {
xp = x;
x = x.next;
t = t.next;
}
while(t.next != null){
yp = y;
y = y.next;
t = t.next;
}
// System.out.println("x= "+x.val+" y= "+ y.val);
// if(xp != null) System.out.println("xp= "+xp.val);
// if(yp != null) System.out.println("yp= "+yp.val);
// first adjust previous pointer of two nodes
// later swap the next pointers of both nodes
// CASE-1: case nodes have previous pointer
// and they are not start and end node
if(xp != null && yp != null ){
xp.next = y;
yp.next = x;
}
// CASE-2: x and y nodes are first and last
// this case xp is null
else if (xp == null && yp != null){
head = y;
yp.next = x;
}
t = y.next;
y.next = x.next;
x.next = t;
return head;
}
public static Node getNodeListHead(int nodes){
int idx = nodes-1;
Node head = new Node(nodes, null);
while(idx >= 1){
head = new Node(idx, head);
idx--;
}
return head;
}
}
Refer to geeks4geeks for all boundary cases:
http://www.geeksforgeeks.org/swap-kth-node-from-beginning-with-kth-node-from-end-in-a-linked-list/
For singly linked list of size N, find the Kth element and then N-K+1 th element and exchange their values
And as Jonathan said, you have to take care of special cases and keep track of additional pointers to do the swap. But the crux is you have to swap the Kth element with the N-K+1th element

Applying bubble sort on linked list gives wrong output in c

I am trying to sort a linked list using bubble sort.But it gives segmentation problem
My logic to do so is below:
Note: Please note that i have to use only pass by reference every where (no return and global declaration for nodes)
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
final=*List
for (i = 0; i < size - 1; i++)
{
first =final;
second = first -> link;
for (j = 0; j < size; j++)
{
if (first -> data < second -> data)
{
temp = first -> data;
first -> data = second -> data;
second -> data = temp;
}
first = first -> link;
}
} * List = first;
}
It's function call is :
bubble_sort(&start,val);
Could any one please help me in correcting the logic ?
EDIT: My full code:
#include <stdio.h>
//#include <conio.h>
#include <malloc.h>
/* structure containing a data part and link part */
struct node
{
int data;
struct node * link;
};
typedef struct node node;
node * start, * visit, * newnode;
//start=NULL
///////////////////////////////// Function declaration ///////////////////
void append(node * * q, int num);
void displaylist(node * start);
void bubble_sort(node * * List, int val);
//////////////////////////////////////////////////////////////////////////////////////////
void append(node * * q, int num)
{
node * temp, * temp2;
temp = * q;
//temp= (node* )malloc(sizeof (node));
if (temp == NULL) /* if the list is empty, create first node */
{
temp = (node * ) malloc(sizeof(struct node)); * q = temp;
} else
{
temp2 = * q;
while (temp2 -> link != NULL)
{
temp2 = temp2 -> link;
}
temp = (node * ) malloc(sizeof(struct node));
temp2 -> link = temp;
}
temp -> data = num;
temp -> link = NULL;
}
///////////////////////////////////////////////////////////////////////
void displaylist(node * start)
{
visit = start;
/* traverse the entire linked list */
while (visit != NULL)
{
printf("%d ", visit -> data);
visit = visit -> link;
}
}
/////////////////////////////////////////////////////////////////////////////////
/*
void bubble_sort(node **List,int size)
{
int i,j,temp;
node*first;
node*second;
node*final;
final=*List;
for(i=0;i<size-1;i++)
{
first=final;
second=first->link;
for(j=1;j<size;j++)
{
if( first->data<second->data)
{
temp=first->data;
first->data=second->data;
second->data=temp;
}
first=first->link;
}
}
*List=first;
} */
//////////////////////////////////////////////////////////////////////////////////////
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
for (i = 0; i < size; i++)
{
first = * List;
for (j = 0; j < size - 1; j++)
{
if (first -> data < first -> link -> data)
{
temp = first -> data;
first -> data = first -> link -> data;
first -> link -> data = temp;
}
first = first -> link;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
main()
{
start = NULL;
int val, n, size;
char ch;
struct node * new;
new = NULL;
printf("\nEnter the size desired size of Linked list: \n");
scanf("%d", & size);
for (ch = 0; ch < size; ch++)
{
printf("\nEnter a value: ");
scanf("%d", & val);
append( & new, val);
}
start = new;
displaylist(start);
printf("\nApplying Bubble sort on Linked list: \n");
bubble_sort( & start, val);
displaylist(start);
printf("\n");
}
Assumed Val is number of nodes in list, you are actually not sorting a linked list but instead swapping the values from one node to another in order to sort it.
bubble_sort( &start, size); change this as well should fix it(pass size not val)
try this.
void bubble_sort(node **List, int val)
{
int i,j,temp;
node *first;
node *second;
node *final;
for(i = 0; i < val; i++)
{
first = *list
for(j = 0; j < val-1; j++)
{
if(first->data < first->link->data)
{
temp = first->data;
first->data = first->link->data;
first->link->data = temp;
}
first = first->link;
}
}
}
I believe you are getting a segmentation fault because you're trying to access a Null pointer as a node, in the inner for-loop.
for (j = 0; j < val; j++)
this should be:
for (j = 0; j < val - 1; j++)
Because in your solution, when j = val-1, it will still try and access first->link->data, however, first->link is Null.

Resources