competitve programming Dijkstra - c

can any one tell me where is the error in this program please it will be really helpful , i did my best to solve this problem ,this code is passing only two test cases
Given an undirected graph and a starting node, determine the lengths of the shortest paths from the starting node to all other nodes in the graph. If a node is unreachable, its distance is -1. Nodes will be numbered consecutively from to , and edges will have varying distances or lengths.
Here is the question https://www.hackerrank.com/challenges/dijkstrashortreach/problem
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
// Node
typedef struct node {
int data;
// Lower values indicate higher priority
int priority;
struct node* next;
} Node;
// Function to Create A New Node
Node* newNode(int d, int p)
{
Node* temp = (Node*)malloc(sizeof(Node));
temp->data = d;
temp->priority = p;
temp->next = NULL;
return temp;
}
// Return the value at head
int peek(Node** head)
{
return (*head)->data;
}
// Removes the element with the
// highest priority form the list
void pop(Node** head)
{
Node* temp = *head;
(*head) = (*head)->next;
free(temp);
}
void updateprt(Node** head, int data) {
if ((*head)->data == data)
{
Node* temp = *head;
*head = (*head)->next;
free(temp);
return;
}
Node* prev = *head;
while ((prev->next)->data != data) {
prev = prev->next;
}
Node* start = prev->next;
prev->next = start->next;
free(start);
}
// Function to push according to priority
void push(Node** head, int d, int p)
{
Node* start = (*head);
// Create new Node
Node* temp = newNode(d, p);
if (*head == NULL) {
*head = temp;
return;
}
// Special Case: The head of list has lesser
// priority than new node. So insert new
// node before head node and change head node.
if ((*head)->priority > p) {
// Insert New Node before head
temp->next = *head;
(*head) = temp;
}
else {
// Traverse the list and find a
// position to insert new node
while (start->next != NULL &&
start->next->priority < p) {
start = start->next;
}
// Either at the ends of the list
// or at required position
temp->next = start->next;
start->next = temp;
}
}
// Function to check is list is empty
int isEmpty(Node** head)
{
return (*head) == NULL;
}
struct adjlistnode {
int data;
struct adjlistnode* next;
};
struct adjlist {
struct adjlistnode* head;
};
struct graph {
int v;
struct adjlist* array;
};
struct graph* creategraph(int v) {
struct graph* G = (struct graph*) malloc(sizeof(struct graph));
G->v = v;
int i;
G->array = (struct adjlist*)malloc(sizeof(struct adjlist)*v);
for (i = 0; i < v; i++) {
G->array[i].head = NULL;
}
return G;
}
int Distance[100000], path[50];
struct adjlistnode* getnewnode(int ver) {
struct adjlistnode* newnode = (struct adjlistnode*)malloc(sizeof(struct adjlistnode));
newnode->data = ver;
newnode->next = NULL;
return newnode;
}
void addedge(struct graph* G, int src, int dest, long int w, long int** weight) {
struct adjlistnode* temp;
temp = getnewnode(dest);
temp->next = G->array[src].head;
G->array[src].head = temp;
temp = getnewnode(src);
temp->next = G->array[dest].head;
G->array[dest].head = temp;
if (weight[src][dest] != 0 || weight[dest][src] != 0 && w < weight[src][dest]) {
weight[src][dest] = w;
weight[dest][src] = w;
}
if (weight[src][dest] == 0) {
weight[src][dest] = w;
weight[dest][src] = w;
}
}
void printgraph(struct graph* G) {
for (int i = 0; i < G->v; i++) {
struct adjlistnode* temp = G->array[i].head;
printf("%d-> ", i);
while (temp) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
}
void Dijkstra(Node** queue, struct graph* G, int s, long int** weight) {
int v, w, d;
push(queue, s, 0);
for (int i = 0; i < 100000; i++) {
Distance[i] = -1;
}
Distance[s] = 0;
while (!isEmpty(queue)) {
v = peek(queue);
pop(queue);
struct adjlistnode* temp = G->array[v].head;
while (temp) {
w = temp->data;
d = Distance[v] + weight[v][w];
//To update the distance of w check the below two conditions
if (Distance[w] == -1) {
Distance[w] = d;
push(queue, w, d);
path[w] = v;
}
if (Distance[w] > d)
{
Distance[w] = d;
path[w] = v;
updateprt(queue, w);
push(queue, w, d);
}
temp = temp->next;
}
}
}
int main()
{
int t;
scanf("%d", &t);
while (t) {
Node* pq = NULL;
int v;
int e;
scanf("%d %d", &v, &e);
long int** weight = (long int**)malloc(sizeof(long int*)*v);
for (int i = 0; i < v; i++)
weight[i] = (long int*)malloc(sizeof(long int)*v);
struct graph* G = creategraph(v);
int u, w;
long int l;
for (int i = 0; i < e; i++) {
scanf("%d %d %ld", &u, &w, &l);
addedge(G, u - 1, w - 1, l, weight);
}
int s;
scanf("%d", &s);
// printgraph(G);
//printf("\n");
Dijkstra(&pq, G, s - 1, weight);
for (int i = 0; i < G->v; i++) {
if (i == s - 1)
continue;
printf("%d ", Distance[i]);
}
/* while (!isEmpty(&pq)) {
printf("%d ", peek(&pq));
pop(&pq);
}*/
return 0;
}
system("pause");
}

Your biggest issue is with your priority queue, which you implement as simple linked list. You seem to be confused about when and how to use a pointer to node pointer.
For example, this function:
int isEmpty(Node **head) ...
only inspects the list. It doesn't modify it, so it is enough to pass a node pointer:
int isEmpty(Node *head) ...
This function doesn't modify the contents of the nodes, either, so this could be made explicit:
int isEmpty(const Node *head) ...
On the other hand, the push, pop and updateprt functions must be able to change the head via a pointer, so they require a pointer to a node pointer. Your pop function, which always changes the head, does this. The other functions look like this:
void push(Node** head, int d, int p)
{
Node* start = (*head);
// ... do stuff with start, leave head alone ...
}
Here, you have just used the pointer to node pointer as an overly obscure way to pass in information about the head, but you never modify it (except in the special case of inserting into an ampty list).
Here's how that push function should look like:
void push(Node **head, int d, int p)
{
Node *temp = newNode(d, p);
while (*head && (*head)->priority < p) {
head = &(*head)->next;
}
temp->next = *head;
*head = temp;
}
Note how there aren't any special cases. When you call push(&queue, ...), you pass the address of the head pointer and you can modify the local variable queue in the calling function by assigning to *head. When you walk through the list with head = &(*head)->next, head holds the address of the next field of the previous node, which you can also modify via *head. The pointer to a pointer adds one level of indirection and tells you where you have come from and lets you modify that value.
In the same vein, you can change (and simplify) your updateptr function:
void updateprt(Node** head, int data)
{
while (*head && (*head)->data != data) {
head = &(*head)->next;
}
if (*head) pop(head);
}
With these changes, your program should work, but there are other things to note:
if (weight[src][dest] != 0 || weight[dest][src] != 0 && w < weight[src][dest]) ...
The condition (w1 == 0 || w2 == 0 && w < w1) is parsed as (w1 == 0 || (w2 == 0 && w < w1)), which probably isn't what you want. The check for zero is ot done correctly, because you never initialize weight. (You could use calloc instead of malloc to create a zero-initialized array.)`
But why have a separate array of weights at all? You could store the weight with each edge:
struct adjlistnode {
int data; // destination vertex
int weight;
struct adjlistnode* next;
};
The same goes for the arrays:
int Distance[100000], path[50];
Both arrays provide one entry for each vertex. The first one is too generous ("I'll allocate a bit more, just in case ..."), the second could be too small. (You don't need the path for the task, but it's always nice to be able to verify it. The variable isn't a path, however, it holds the next step towards the starting point for each vertex.)
The competition rules say that there are at most 3,000 nodes, so you could just dimension your arrays with [3000], but you cold also make them part of the graph structure and allocate according to the number of vertices.
Good luck!

Related

Sorting a single linked list algorithm in C does not work(Bubblesort with swapping the Nodes, not the data is used)

currently i'm trying out some algorithms. The Bubblesort with swapping the data works fine, but when i try to use the swap adress function the program ends with an error. I hope someone can help me
The structure i use is:
struct Node_s{
int data;
struct Node_s *next;
};
typedef struct Node_s Node_t;
Thats my function to swap the nodes:
Node_t* swap_adr(Node_t *ptr1, Node_t *ptr2)
{
Node_t *temp;
temp=ptr2->next;
ptr2->next=ptr1;
ptr1->next=temp;
return ptr2;
}
Thats the function which calculates the length of the list:
int len(Node_t* head)
{
Node_t* temp = head ;
int i = 0 ;
while(temp!=NULL)
{
i++;
temp=temp->next ;
}
return i ;
}
Thats the BubbleSort funciton which does not work:
void bubbleSort(Node_t* head)
{
int length=len(head);
Node_t* temp;
int i, j, swapped;
Node_t* p1,*p2;
for(i=0;i<=length;i++)
{
temp = head;
swapped = 0;
for (j = 0; j < length - 1; j++)
{
p1 = temp;
p2 = p1->next;
if (p1->data > p2->data)
{
/* update the link after swapping */
temp = swap_adr(p1, p2);
swapped = 1;
}
temp = temp->next;
}
}
}
The strange thing is, this code works, i don't understand why?
void bubbleSort(Node** head)
{
int length=len(*head);
Node** temp;
int i, j, swapped;
Node* p1,p2;
for (i = 0; i <= length; i++)
{
temp = head;
swapped = 0;
for (j = 0; j < length - i - 1; j++)
{
p1 = *temp;
p2 = p1->next;
if (p1->data > p2->data)
{
/* update the link after swapping */
*temp = swap(p1, p2);
swapped = 1;
}
temp = &(*temp)->next;
}
if (swapped == 0)
break;
}
return;
}
You need an extra variable for the previous node (i.e. the one before p1).
When you swap the next pointers in the loop, you have to change prev->next from p1 to p2
Here is some refactored code. It is annotated. I've compiled it but not tested it:
#include <stdio.h>
typedef struct node {
int data;
struct node *next;
} Node_t;
void
bubbleSort(Node_t *head)
{
Node_t *temp;
Node_t *rhs;
Node_t *lhs;
Node_t *prev;
// get list total length
int length = 0;
for (temp = head; temp != NULL; temp = temp->next)
++length;
// reduce length by one on each pass (the last element on each pass is
// correct -- no need to rescan)
for (; length > 1; --length) {
int swapped = 0;
// get the two pointers
rhs = NULL;
lhs = head;
if (lhs != NULL)
rhs = lhs->next;
prev = NULL;
int i = 1;
for (; rhs != NULL; prev = lhs, lhs = rhs, rhs = rhs->next, ++i) {
// no need to traverse the entire list on subsequent passes
if (i >= length)
break;
// nodes are in sort
if (lhs->data <= rhs->data)
continue;
// swap the node pointers
temp = lhs->next;
lhs->next = rhs->next;
rhs->next = temp;
// link previous node to new lhs (i.e. rhs)
if (prev != NULL)
prev->next = rhs;
// new list head
else
head = rhs;
// swap lhs/rhs so that the for loop works
temp = lhs;
lhs = rhs;
rhs = temp;
// say a swap was done
swapped = 1;
}
// early escape if no swap
if (! swapped)
break;
}
}
If you want to swap addresses, then you have to pass the addresses of the two elements you want to swap.
For example, if you want to swap pointers, which are basically addresses, then you have to pass the addresses of the addresses. Thus:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
void node_swap(struct node **p, struct node **q) // Pass the address of (struct node*)
{
struct node *tmp = *p;
*p = *q;
*q = tmp;
}
int main(void)
{
struct node *n1 = malloc(sizeof *n1);
struct node *n2 = malloc(sizeof *n2);
n1->data = 1;
n2->data = 2;
printf("N1 = %d\n", n1->data);
printf("N2 = %d\n", n2->data);
node_swap(n1, n2);
printf("N1 = %d\n", n1->data);
printf("N2 = %d\n", n2->data);
free(n1);
free(n2);
}
Output:
N1 = 1
N2 = 2
N1 = 2
N2 = 1
EDIT You probably should avoid typedefing your structs. But in case you insist on that, here's how your code should look like:
struct node {
int data;
struct node *next;
};
typedef struct node node_s;
typedef struct node *node_ptr;
void node_swap(node_ptr *p, node_ptr *q) // Pass the address of p and q
{
node_ptr tmp = *p;
*p = *q;
*q = tmp;
}

Trouble declaring an adjacency list in C

It's the very first time I am trying to use a adjacency list and I am really confused with its declaration
This is my node structure and the list for using as my first node, what I called head
typedef struct node
{
int NodeNum;
struct node *next;
}node;
typedef struct list
{
node *head;
}list;
and here is where I try to allocate the correct amount of memory for the array of heads that the user wants
int n;
scanf("%d", &n);
list *NodList[n] = {0};
for(int i = 0; i < n; i++)
{
NodList[i] = (list*)malloc(sizeof(list));
NodList[i]->head = NULL;
}
Here is the thing, I want the user to tell me how many nodes I'll have and then allocate the correct amount of memory for it, but apparently I am getting something wrong here
Expanding a little bit on Antonin GAVREL's answer. Basically using the same linked list he brought up, and introducing an AListEntry used to represent the adjacency list. Each AListEntry points to a vertex and that vertex's adjacent vertices. It also points to the next AListEntry.
You could, instead, also just replace the AListEntry with a dynamically allocated array of Node pointers if you know the number of vertices ahead of time. Each index in the array will correspond to a vertex, and the pointer will point to the head Node pointer of your adjacent vertices for that vertex, which will a linked list. You'll end up with an array of linked lists.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int value;
struct Node* next;
} t_Node;
t_Node* createNode(int value)
{
t_Node* node = (t_Node*)malloc(sizeof(t_Node));
node->value = value;
node->next = NULL;
return node;
}
t_Node* addNode(int value, t_Node* node)
{
node->next = createNode(value);
return node->next;
}
typedef struct AListEntry
{
t_Node* vertex;
t_Node* adjacentVertices;
struct AListEntry* next;
} t_AListEntry;
t_AListEntry* createAListEntry(
t_Node* vertex,
t_Node* adjacentVertices)
{
t_AListEntry* entry = (t_AListEntry*)malloc(sizeof(t_AListEntry));
entry->vertex = vertex;
entry->adjacentVertices = adjacentVertices;
entry->next = NULL;
return entry;
}
void printAListEntries(t_AListEntry* aList)
{
while (aList != NULL)
{
printf("%d -> [ ", aList->vertex->value);
t_Node* node = aList->adjacentVertices;
while (node != NULL)
{
printf("%d ", node->value);
node = node->next;
}
printf("]\n");
aList = aList->next;
}
}
int main()
{
t_Node* v1 = createNode(1);
t_Node* v1Adjacents = createNode(2);
addNode(3, v1Adjacents);
t_AListEntry* aList = createAListEntry(v1, v1Adjacents);
t_Node* v2 = createNode(2);
t_Node* v2Adjacents = createNode(1);
addNode(3, v2Adjacents);
aList->next = createAListEntry(v2, v2Adjacents);
t_Node* v3 = createNode(3);
t_Node* v3Adjacents = createNode(1);
addNode(2, v3Adjacents);
aList->next->next = createAListEntry(v3, v3Adjacents);
printAListEntries(aList);
return 0;
}
Example where the array is declared on the stack as a VLA:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node
{
int value;
struct Node *next;
} t_Node;
bool build_linked_list(t_Node **head, int n) {
t_Node *node;
t_Node *tmp;
static int a = 1024; // just for test purposes
if (!(node = (t_Node*)malloc(sizeof(t_Node))))
return false;
node->value = a;
*head = node;
for(int i = 1; i < n; i++)
{
if (!(tmp = (t_Node*)malloc(sizeof(t_Node))))
return false;
tmp->value = i + a;
node->next = tmp;
node = tmp;
}
a <<= 1; // so that other nodes have different values
return true;
}
int main(void) {
int n;
scanf("%d", &n);
t_Node *nodes[n];
for (int i = 0; i < n; i++) {
if (!build_linked_list(&nodes[i], n)) {
perror("Failed to malloc node");
return 1;
}
}
for (int i = 0; i < n; i++) {
while (nodes[i]) {
printf("%d\n", nodes[i]->value);
nodes[i] = nodes[i]->next;
}
}
return 0;
}
Let me know if you have any question

Having a trouble with linked lists (adding and printing)

I'm too new on data structures, actually i began yesterday. Here is the code:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int x;
node *next;
};
void addToList(node *r, int a);
void printList(node *r);
int main()
{
node *root;
root = NULL;
for (int i = 0; i < 5; i++)
{
int a;
scanf("%d", &a);
addToList(root, a);
}
printList(root);
return 0;
}
void addToList(node *r, int a)
{
while (r != NULL)
r = r -> next;
r = (node *)malloc(sizeof(node));
r -> x = a;
r -> next = NULL;
}
void printList(node *r)
{
while (r != NULL)
{
printf("%d ", r -> x);
r = r -> next;
}
printf("\n");
}
I expect the program gets new 5 elements into the list and then prints them. But end of the program nothing is happening. What is my fault?
The problem is in the addToList() function. If you want to update the root node of the list you have to define your function like that:
void addToList(node **r, int a)
Otherwise, you're sending the pointer to root and doing whatever you doing inside the function. But it doesn't affect root's value on main() and it remains NULL.
If you want to change the value of the pointer, you have to send from main() the address of the pointer to the function ==> addToList(&root, a);.
So now we can update where root points to. But it's not enough because you want root to always point to the beginning of the list ==> you want to update it only in the first call to addToList().
Last problem is to add the new created node as the last node in the list. You can do that by saving a temporary pointer to the last node. See my comments in the code (marked my changes with <<<):
void addToList(node **root, int a) <<<
{
node *r = *root; <<<
node *last = NULL; <<<
while (r != NULL) {
last = r; <<<
r = r -> next;
}
r = (node *)malloc(sizeof(node));
r -> x = a;
r -> next = NULL;
if (last == NULL) { <<<
// this is true only on the first call to
// addToList, so we update root only once
*root = r;
} else {
// all other times we add the new node to be the last one
last->next = r;
}
}
You have root = NULL but your addtoList function checks if root !=NULL. So the test fails there and nothing gets added.
You should have something like this instead:
void addToList(node *r, int a) {
struct node *temp;
temp=(struct node *)malloc(sizeof(struct node));
temp->data = a;
if (r== NULL) {
r = temp;
r->next = NULL;
}
else {
temp->next = r;
r = temp;
}
}
Here, the first mistake is that you have not taken the *root pointer variable as global, so it will not update the value of the *root whenever a new node is inserted. It will keep the value of *root as NULL.
The below code has comments in it, which will explain the various mistakes done by you very easily.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int x;
node *next;
};
node *root; //Declaring the *root as global
void addToList(int a);
void printList();
//removing the *root as parameter from both the functions
int main()
{
root = NULL;
for (int i = 0; i < 5; i++)
{
int a;
scanf("%d", &a);
addToList(a);
}
printList();
return 0;
}
void addToList(int a)
{
//Declaring a temporary pointer(*temp) to avoid the value loss of the *root pointer
node *temp=root;
//Declaring a new node to save the data taken from the user
node *nn = (node *)malloc(sizeof(node));
//Assigning the values to the new node(*nn)
nn->x=a;
nn->next=NULL;
//Checking that the root node is NULL or not
//If root is empty, then new node is assigned to *root
if(root == NULL)
{
root=nn;
}
//Else, we will first find the last node of the linklist using the *temp pointer
else
{
while (temp->next != NULL)
temp = temp -> next;
//Assigning the new node after the last node of the linklist
temp->next=nn;
}
}
void printList()
{
node *r=root;
while (r != NULL)
{
printf("%d ", r -> x);
r = r -> next;
}
printf("\n");
}

Linked List Pointer Without A Cast Error

I'm getting assignment makes pointer from integer without a cast errors on lines 46 and 53, the two lines with double asterisks on either side, and for the life of me, I cannot figure out why. Linked lists are very new to me, I don't know how they work completely yet.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node_def
{
int data;
struct node_def *next;
};
typedef struct node_def node;
node *makeNode (int a);
node *insertFront(node *head,node *new);
void printList(node *head);
int numNodes = 0;
int main()
{
srand(time(0));
int r = rand() % 10000;
int i = 0;
node *head = NULL;
node *tmp = NULL;
printf("How many nodes? ", numNodes);
scanf("%d", numNodes);
printf("\n");
head = insertFront(head, tmp);
for(i = 0; i < numNodes; i++)
{
makeNode(r);
printList(head);
}
printf("\n");
return 0;
}
node *makeNode (int a)
{
node *new = malloc(sizeof(node));
**new = a;**
return new;
}
node *insertFront(node *head, node *new)
{
**new->data = head;**
new->next = new;
return 0;
}
void printList(node *head)
{
int j = 0;
for(j = 0; j < numNodes; ++j)
{
while (head != NULL)
{
printf(" %4d", head->data);
head = head->next;
}
if(j % 10 == 0)
printf("\n");
}
return;
}
new = a is meant to make new nodes and assign them a random number from 0 - 9999.
You try to assign r to new, but new is a struct.
You make a pointer to struct : node *new
What you want to do is assigning r to new->data, which is an int.
node *insertFront(node *head, node *new)
{
**new->data = head;** // ** is meaningless
new->next = new; // new is a reserved key word, don't use it this way
return 0;
}
What you try to do is to put a NULL pointer as the head of your list.
Just push element into it within your makeNode function.
insert like this :
void createNode(node *head)
{
Node *new_node = malloc(sizeof(Node*));
new_node->data = rand() % 100000;
new_node->next = NULL;
if(head == NULL)
head = new_node;
else if(head != NULL)
//Here you have to adapt your list, search (linked list crud functions)
}
You have a bad understanding about what pointers are.
Hope it helps bro

Exception thrown in linked list

I need to write a function that returns the size of a linked list. It seems simple enough, but I get an exception when I try to advance my pointer.
This is the code:
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
This is the code that defines the linked list:
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
And this is the code that creates the list:
List *create_list(int n)
{
List *list = (List*) calloc(n,sizeof(List));
list->head = NULL;
return list;
}
Lastly, I have inserted data (numbers) into the list using these two functions: (so don't think the lists are empty).
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
List_node *mk_node(int data, int n)
{
List_node *node = (List_node *)calloc(n, sizeof(List_node));
node->data = data;
return node;
}
Using a breakpoint I discovered that the problem lies in p = p->next, but I don't understand why.
Thank you very much.
edit - I did not think the full code is necessary, but here it is:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "List.h"
void merge(List *small_list, List *big_list)
{
List_node *x, *y;
y = small_list->head;
x = big_list->head;
t = x->prev;
// while (y < x) //If there are smaller numbers on the small list, insert them first
// {
// insert(y,t)
// t = t->next;
// y = y->next;
// }
while (y != NULL && x->next != NULL)
{
if (x <= y && x->next >= y)
{
insert(y, x);
y = y->next;
}
else
x = x->next;
}
while (y != NULL)
{
insert(y, x);
y = y->next;
}
}
void main()
{
List *L1, *L2, *big_list, *small_list;
int num1, num2;
int i;
int a, b;
create_list(5,&L1);
create_list(3,&L2);
printf("Insert first number into L1\n");
scanf("%d", &num1);
node = mk_node(0,5);
insert_first(node, &L1);
for (i = 0; i<5; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num1);
next = mk_node(&num1,5);
insert(next, node);
node = next;
}
printf("Insert first number into L2\n");
scanf("%d", &num2);
node = mk_node(0,3);
insert_first(node, &L2);
for (i = 0; i<3; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num2);
next = mk_node(&num2,3);
insert(next, node);
node = next;
}
//If lists are in descending order, reverse them to ascending order
//if (L1->head > L1->head->next)
// reverse(L1);
// if (L2->head > L2->head->next)
// reverse(L2);
int size_L1 = List_size(L1);
int size_L2 = List_size(L2);
if (size_L1 <= size_L2)
{
big_list = L2;
small_list = L1;
}
else
{
big_list = L1;
small_list = L2;
}
merge(small_list, big_list);
print_list(L3);
getchar(); getchar();
}
As you can see, I inserted the numbers using the function insert(). I hope it is okay.
The function reverse is: (I really hope it works, I translated it from pseudo-code)
List reverse(List *list)
{
List_node *x, *y, *z;
if (list->head == NULL || list->head->next == NULL)
{
return *list;
}
x = list->head;
y = list->head->next;
z = list->head->next->next;
x->next = NULL;
while (z != NULL)
{
y->next = x;
x = y;
y = z;
z = z->next;
}
y->next = x;
list->head = y;
}
Basically, this is an assignment that says I have two 2-directional sorted linked lists, and I'm supposed to merge them into one big sorted linked list.
As for the exception - Unhandled exception at 0x00E21766 in Lists.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.
Edit - the print_list function:
void print_list(List *list)
{
List_node *p;
p = list->head;
printf("The linked list consists of: ");
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
The problem is in code you did not show, because all the code you give is fine (*).
I could use your structs and functions to :
create a List
add a first node (with insert_first)
add other nodes (with insert)
get the size (using List_size)
display the data value of every node
free the nodes and the list
Here's the full code :
#include <stdio.h>
#include <malloc.h>
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
List *create_list()
{
List *list = (List*) malloc(sizeof(List));
list->head = NULL;
return list;
}
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
/* my own additions */
List_node *mk_node(int data) {
List_node *node = (List_node *) malloc(sizeof(List_node));
node->data = data;
return node;
}
void delete_list(List *list) {
List_node *node = list->head;
while (node != NULL) {
List_node *next = node ->next;
free(node);
node = next;
}
free(list);
}
int main() {
List* list = create_list();
List_node *node, *next;
int i;
node = mk_node(0);
insert_first(node, list);
for (i=1; i<5; i++) {
next = mk_node(i);
insert(next, node);
node = next;
}
int n = List_size(list);
printf("size : %d\n", n);
node = list->head;
while (node != NULL) {
printf("node val : %d\n", node->data);
node = node->next;
}
delete_list(list);
return 0;
}
(*) Your code is not perfect because List_node struct contains a pointer prev that is never used, so you end with a single-linked list with every third value unused.
I added a comment above that I copied your code into my compiler and that it doesn't compile, so it won't run: the calls to create_list don't compile: they return a value as function return, not in a parameter; there are undeclared variables. Further, it is useless to give create_list and mk_node a parameter: they will allocate an array, not create a single list element. A call of calloc(1, sizeof(your_thing)) would suffice. After fixing these erors, several bugs became apparent:
in insert_first(node, &L2); you give it the address of the list, which is already a pointer. Remove the '&' (the compiler should have complained!).
same for List_size(&L1); L1 is already a pointer. Remove the '&'.
in: if (x <= y ...) you compare memory addresses. Change to: if (x->data <= y->data...)
in that statement the part "x->next >= y" also compares memory address, and I don't see why it is needed. I removed it.
The real problem seems to be in merge. You should either merge the lists into L1, or into L2, and preferably should create a result list. But you "randomly" insert an element into L1, then into L2, then again into L1, etcetera. In my test it ran indefinitly. The following merge works fine:
List *merge(List *small_list, List *big_list)
{
List_node *x, *y, *r;
List *result= create_list();
y = small_list->head;
x = big_list->head;
if (x->data < y->data)
{result->head= x; x= x->next;}
else {result->head= y; y= y->next;}
r= result->head;
while (y != NULL && x != NULL)
{
if (x->data < y->data)
{
r->next= x;
x = x->next;
}
else {
r->next= y;
y = y->next;
}
r= r->next;
}
while (y != NULL)
{
r->next= y;
y = y->next;
r= r->next;
}
while (x != NULL)
{
r->next= x;
x = x->next;
r= r->next;
}
r->next= 0;
return (result);
}
So the problem is that you allocate the list head, but never allocate memory for the list elements. Serge added mk_node which does the allocation (so Serge solved it).

Resources