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
Related
I am trying to create a function that turns an array to a linked list for further usage
typedef struct ListNode {
int val;
struct ListNode *next;
} ListNode;
ListNode * create_linked_list(int *nums , int count)
{
ListNode * ptr = (ListNode*)malloc(count*sizeof(ListNode));
for (int i =0; i < count; i++)
{
ListNode new;
new.val = nums[i];
ptr[i] = new;
}
for (int j=0; j < count; j++)
{
if ( j>=count )
ptr[j].next = NULL;
else
ptr[j].next = &ptr[j+1];
}
return ptr;
}
int main()
{
int nums[] = {2,4,3};
ListNode *node_ptr = create_linked_list(nums , sizeof(nums)/sizeof(nums[0]));
ListNode start = node_ptr[0];
}
I have this simple function that turns an array of integers into a linked list, assume the last node in the list is called x_node now x_node.next is equal to NULL because it is defined inth the second for loop in create_linked_list, but when I try to add a while loop in the main it results in a segmentation fault
int main()
{
int nums[] = {2,4,3};
ListNode *node_ptr = create_linked_list(nums , sizeof(nums)/sizeof(nums[0]));
ListNode start = node_ptr[0];
while (start.next != NULL)
{
printf("%d \n", start.val);
start = *start.next; // at the last element it should stop but a segfault is thrown
}
}
If you wan t to loop over a linked list, you need to create the list properly in the first place. Your create_linked_list function is totally wrong.
You want this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct ListNode {
int val;
struct ListNode* next;
} ListNode;
ListNode* create_linked_list(int* nums, int count)
{
ListNode* head = NULL;
ListNode *previous = NULL;
for (int i = 0; i < count; i++)
{
// create new node and put value into it
ListNode *new = malloc(sizeof(ListNode));
new->val = nums[i];
new->next = NULL;
if (i == 0) // head will point to the first element
head = new;
if (previous)
{
// if previous node exists, link to newly created node
previous->next = new;
}
previous = new; // new node becomes previous node
}
return head;
}
int main()
{
int nums[] = { 2,4,3 };
ListNode* head = create_linked_list(nums, sizeof(nums) / sizeof(nums[0]));
// now it's up to you to write the print_list function
// print_list(head);
}
Now writing the print_list function should be easy. Hint: take a pencil and a piece if paper and draw the nodes with arrows as pointers pointing to the next node.
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!
I want to insert a node int the end of the linked list, but I don't know how to achieve.
#include <stdio.h>
#include <stdlib.h>
typedef struct Info* PtrToNode;
struct Info {
int number;
PtrToNode next;
};
typedef struct Info* list;
typedef struct HashNode* HashTable;
struct HashNode {
list Heads;
int size;
};
HashTable createTable(int size) {
HashTable H = (HashTable)malloc(sizeof(struct HashNode));
H->size = size;
H->Heads = (PtrToNode)malloc(H->size * sizeof(struct Info));
for (int i = 0; i < H->size; ++i)
{
H->Heads[i].number = 0;
H->Heads[i].next = NULL;
}
return H;
}
int Hash(int n, int size) {
return n % size;
}
void insert(HashTable H, int index, int number) {
int pos = Hash(number, H->size);
list check = H->Heads[pos].next;
while (check) {
check = check->next;
}
PtrToNode newNode = (PtrToNode)malloc(sizeof(struct Info));
newNode->number = number;
newNode->next = NULL;
check = newNode;
}
I want append in the insert function, but the params "check" like temporary, and if I "while" the H->heads[pos], the node always in the head.
You are confusing arrays and lists. H->Heads[i].number is not the proper way to access a list. For a list you need H->Heads->number and H->Heads->next. The next pointer will point to the next element of the list
Basically you have an array of numbers with an extra unused pointer.
For the create function given to add an element at the end, you need to realloc the entire array with new size. However, this is probably not what you want.
You need to modify the create function to make a true list and then you can append.
Code below, inserts at the end, you can modify to insert at a particular index.
typedef struct Info* PtrToNode;
struct Info {
int number;
PtrToNode next;
};
typedef struct Info* list;
typedef struct HashNode* HashTable;
struct HashNode {
list Heads;
int size;
};
HashTable createTable(int size) {
HashTable H = (HashTable)malloc(sizeof(struct HashNode));
H->size = size;
H->Heads = malloc(sizeof(struct Info));
H->Heads->number = 0;
H->Heads->next = NULL;
list curr = H->Heads;
list nextval;
for (int i = 1; i < H->size; ++i)
{
nextval = malloc(sizeof(struct Info));
nextval->number = 0;
nextval->next = NULL;
curr->next = nextval;
curr = curr->next;
}
return H;
}
int Hash(int n, int size) {
return n % size;
}
void insert(HashTable H, int index, int number) {
int pos = Hash(number, H->size);
list check = H->Heads;
while (check->next) {
check = check->next;
}
PtrToNode newNode = (PtrToNode)malloc(sizeof(struct Info));
newNode->number = number;
newNode->next = NULL;
check->next = newNode;
(H->size)++;
}
I'm trying to count the number of times a given int occurs in a list, but I'm having a difficult time getting my pointers to work. Can someone spot where is my logic failing? Is it because of how I'm implementing the "follows" "->" in the counting function?
//this is in my .h file
typedef struct list_struct LIST;
///// the rest is in my .c file
typedef struct node {
ElemType val;
struct node *next;
} NODE;
struct list_struct {
NODE *front;
NODE *back;
};
//this is my counting function
int lst_count(LIST *l, ElemType x) {
LIST *current = l;
int count = 0;
while (current != NULL) {
if ((current->front->val) == x) count++;
current = current->front->next;
//in the line above I get the following warning:
//"incompatible pointer types assigning to 'LIST*' (aka 'struct list_struct*') from 'struct node*'"
}
return count;
}
Your problem is in the while loop
You are in a list struct, then you do
current->front->next;
Now you are in a NODE type struct, in the next iteration there is no front in NODE.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
struct node *previous;
} NODE;
int lst_count(NODE *l, int x) {
NODE *current = l;
NODE *start = current; /* so that we wont loose the start*/
int count = 0;
while (current != NULL) {
if ((current->val) == x)
count++;
current = current->next;
}
return count;
}
int main()
{
NODE* p = (NODE*)malloc(sizeof(NODE));
NODE* p1 = (NODE*)malloc(sizeof(NODE));
NODE* p2 = (NODE*)malloc(sizeof(NODE));
NODE* start = p;
p->val = 5;
p->next = p1;
p1->next = p2;
p2->next=NULL;
p1->val = 5;
p2->val = 5;
printf("%d", lst_count(start, 5));
}
I got the function to work thanks to your all advises
int lst_count(LIST *l, int x) {
NODE *current = l->front;
int count = 0;
while (current != NULL) {
if ((current->val) == x) count++;
current = current->next;
}
return count;
}
I have spent a lot of time trying to work on this problem for a class and am at ends. I have found lots of resources regarding arrays and other ways of selecting a pivot but I am just at ends and am really going crazy here, any help would be so much appreciated you can not possibly imagine.
#include <stdlib.h> /*and, malloc*/
#include <stdio.h> /*printf*/
struct listnode {
struct listnode *next;
long value;
};
/*Finds length of list, which is usefull in selecting a random pivot*/
int ListLength (struct listnode *list)
{
struct listnode *temp = list;
int i=0;
while(temp!=NULL)
{
i++;
temp=temp->next;
}
return i;
}
/*Prints list*/
void printList(struct listnode *list)
{
struct listnode *node;
node=list;
printf("\nList Values\n");
while(node!=NULL)
{
printf("%2lo ", node->value);
node=node->next;
}
}
/*Creates a list of desired length*/
struct listnode *createList(int lengthOfList)
{
long i;
struct listnode *node, *space;
space = (struct listnode *) malloc( lengthOfList*sizeof(struct listnode));
for( i=0; i< lengthOfList; i++ )
{ (space + i)->value = 2*((17*i+1)%lengthOfList);
(space + i)->next = space + (i+1);
}
(space+(lengthOfList-1))->next = NULL;
node = space;
return node;
}
/*Prof Brass's test*/
void Brass_test(struct listnode *list)
{
int i;
printf("\nChecking sorted list\n");
for( i=0; i < 100; i++)
{
if( list == NULL )
{
printf("List ended early\n"); exit(0);
}
if( list->value != 2*i )
{
printf("Node contains wrong value\n"); exit(0);
}
list = list->next;
}
printf("Sort successful\n");
}
/*Selects a random pivot point*/
struct listnode *SelectPivot(struct listnode *list)
{
int k, n, i = 0;
n = ListLength(list);
struct listnode *pivot=list;
k=rand()%n;
for (; i < k; ++i)
{
pivot=pivot->next;
}
return pivot;
}
// Sorts a list using quicksort algo with random pivot point
struct listnode *Quicksort(struct listnode *list)
{
// Return NULL list
if (ListLength(list) <= 1) return list;
struct listnode *less=NULL, *more=NULL, *next, *endl, *temp=list;
/*Select a random pivot point*/
struct listnode *pivot = SelectPivot(list);
printf("Pivot Value = %lo\n", pivot->value);
/*Divide & Conquer*/
while(temp != NULL)
{
next = temp->next;
if(temp->value < pivot->value)
{
temp->next = less;
less = temp;
}
else
{
temp->next = more;
more = temp;
}
temp = next;
}
less = Quicksort(less);
more = Quicksort(more);
// Merge
if(ListLength(less)!=0)
{
while(endl != NULL)
{
endl = less->next;
less->next = more;
more = less;
less = endl;
}
return more;
}
else
{
return more;
}
}
int main(void)
{
struct listnode *node;
node = createList(25);
printf("Unsorted List\n");
printList(node);
printf("\nSorted List\n");
node = Quicksort(node);
printf("\nList Count node %d\n", ListLength(node));
printList(node);
/* Brass_test(node);*/
exit(0);
}
So here is the the solution to the problem for those that are curious about the code. I included only the function its self and the helper functions.
Cheers,
#include <stdlib.h> //rand, malloc
#include <stdio.h> //print
#include <time.h>
struct listnode {
struct listnode *next;
long value;
};
//Finds length of list, which is usefull in selecting a random pivot
int ListLength (struct listnode *list)
{
struct listnode *temp = list;
int i=0;
while(temp!=NULL)
{
i++;
temp=temp->next;
}
return i;
}
// Selects a random pivot point
struct listnode *SelectPivot(struct listnode *list)
{
int k, n, i = 0;
n = ListLength(list);
struct listnode *pivot=list;
k=rand()%n; //
for (; i < k; ++i)
{
pivot=pivot->next;
}
return pivot;
}
// Sorts a list using quicksort algo with random pivot point
struct listnode *Quicksort(struct listnode *list)
{
// Return NULL list
if (ListLength(list) <= 1) return list;
struct listnode *less=NULL, *more=NULL, *next, *end, *temp=NULL;
// Select a random pivot point
struct listnode *pivot = SelectPivot(list);
// Remove pivot from list
while(list !=NULL)
{
next = list->next;
if(list->value != pivot->value)
{
list->next=temp;
temp = list;
}
list = next;
}
// Divide & Conq
while(temp != NULL)
{
next = temp->next;
if(temp->value < pivot->value)
{
temp->next = less;
less = temp;
}
else
{
temp->next = more;
more = temp;
}
temp = next;
}
// Recursive Calls
less = Quicksort(less);
more = Quicksort(more);
// Merge
if(less != NULL)
{
end = less;
while(end->next != NULL){
end=end->next;
}
pivot->next=more;
end->next = pivot;
return less;
}
else{
pivot->next = more;
return pivot;
}
}
One problem is with your merge code -- it reverses the less list while prepending it to the more list, which results in garbage.
In case of applying quick sort, the best practice is always to take the FLOOR(n/2) As pivot