double pointer to a node - c

My doubt is regarding pointer only,Here head is a double pointer to Queue if we are using *head than we are accessing the location(or address passed) inside main but when we are using simply head than we are using heading in the current function only which will hold the address of pointer to Queue now when we are doing this head=&(*head)->next the since (*head)->next is itself a address and when we use & before this ,than will a separate block will memory block will be created and hold the address of (*head)->next and we are assigning that address to head
I have this doubt because its like a two step process we cannot directly put the (*head)->next to sore something inside head we need to pass address of address for that we would require a extra block and when the loop will executed say n times than there will be n intermediate blocks?
Please tell me if i am correct or not
and tell the right logic thanks
void queue_push(Queue **head, int d, int p)
{
Queue *q = queue_new(d, p);
while (*head && (*head)->priority < p) {
head = &(*head)->next;
}
q->next = *head;
*head = q;
}
Full program is
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Queue Queue;
struct Queue {
int data;
int priority;
Queue *next;
};
Queue *queue_new(int d, int p)
{
Queue *n = malloc(sizeof(*n));
n->data = d;
n->priority = p;
n->next = NULL;
return n;
}
int queue_pop(Queue **head)
{
assert(*head);
Queue *old = *head;
int res = old->data;
*head = (*head)->next;
free(old);
return res;
}
void queue_remove(Queue **head, int data)
{
while (*head && (*head)->data != data) {
head = &(*head)->next;
}
if (*head) queue_pop(head);
}
void queue_push(Queue **head, int d, int p)
{
Queue *q = queue_new(d, p);
while (*head && (*head)->priority < p) {
head = &(*head)->next;
}
q->next = *head;
*head = q;
}
int queue_empty(Queue *head)
{
return (head == NULL);
}
void queue_print(const Queue *q)
{
while (q) {
printf("%d[%d] ", q->data, q->priority);
q = q->next;
}
puts("$");
}
typedef struct Graph Graph;
typedef struct Edge Edge;
struct Edge {
int vertex;
int weight;
Edge *next;
};
struct Graph {
int v;
Edge **edge;
int *dist;
int *path;
};
Graph *graph_new(int v)
{
Graph *G = malloc(sizeof(*G));
G->v = v;
G->edge = calloc(v, sizeof(*G->edge));
G->dist = calloc(v, sizeof(*G->dist));
G->path = calloc(v, sizeof(*G->path));
return G;
}
void graph_delete(Graph *G)
{
if (G) {
for (int i = 0; i < G->v; i++) {
Edge *e = G->edge[i];
while (e) {
Edge *old = e;
e = e->next;
free(old);
}
}
free(G->edge);
free(G->dist);
free(G->path);
free(G);
}
}
Edge *edge_new(int vertex, int weight, Edge *next)
{
Edge *e = malloc(sizeof(*e));
e->vertex = vertex;
e->weight = weight;
e->next = next;
return e;
}
void graph_edge(Graph *G, int u, int v, int w)
{
G->edge[u] = edge_new(v, w, G->edge[u]);
G->edge[v] = edge_new(u, w, G->edge[v]);
}
void dijkstra(const Graph *G, int s)
{
Queue *queue = NULL;
for (int i = 0; i < G->v; i++) G->dist[i] = -1;
G->dist[s] = 0;
queue_push(&queue, s, 0);
while (!queue_empty(queue)) {
int v = queue_pop(&queue);
Edge *e = G->edge[v];
while (e) {
int w = e->vertex;
int d = G->dist[v] + e->weight;
if (G->dist[w] == -1) {
G->dist[w] = d;
G->path[w] = v;
queue_push(&queue, w, d);
}
if (G->dist[w] > d) {
G->dist[w] = d;
G->path[w] = v;
queue_remove(&queue, w);
queue_push(&queue, w, d);
}
e = e->next;
}
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--) {
Graph *G;
int v, e, s;
scanf("%d %d", &v, &e);
G = graph_new(v);
for (int i = 0; i < e; i++) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
graph_edge(G, u - 1, v - 1, w);
}
scanf("%d", &s);
dijkstra(G, s - 1);
for (int i = 0; i < G->v; i++) {
if (i != s - 1) {
printf("%d ", G->dist[i]);
}
}
puts("");
graph_delete(G);
}
return 0;
}

queue_push() fails to insert a new node correctly.
Only one node's .next is updated. Usually 2 nodes need their .next member updated. One in the original list (previous to the new node's location) and the new one.
I find creating a temporary node before the list, superhead, simplifies code.
void queue_push(Queue **head, int d, int p) {
Queue *q = queue_new(d, p);
Queue superhead; // Only superhead.next member important.
superhead.next = *head;
Queue *previous = &superhead;
while (previous->next && previous->next->priority < p) {
previous = previous->next;
}
q->next = previous->next;
previous->next = q;
*head = superhead.next;
}

Related

segmentation fault testing linked list

I am trying to build and test a linked list in C. But I can't seem to figure out why I am getting segmentation fault from running the test (test_linked_list.c). The problem seems to be from the list_delete function when running gdb, but I can't find where the problem is. Why is this wrong?
linkedlist.c:
#include <stdio.h>
#include <string.h>
#include "linked_list.h"
void list_init(list_t *h) {
*h = NULL;
}
int list_size(const list_t *h) {
node_t *p = *h;
int r = 0;
do {
r += 1;
p = p->next;
} while (p);
return r;
}
int list_empty(const list_t *h) {
return (*h == NULL);
}
void list_insert(list_t *h, node_t *n) {
n->next = *h;
*h = n;
}
node_t *list_find(const list_t *h, int id) {
node_t *p = *h;
while (p) {
if (p->id == id)
return p;
p = p->next;
}
}
node_t *list_find_before(const list_t *h, int id) {
node_t *p = *h;
while (p && p->next) {
if (p->next->id == id)
return p;
p = p->next;
}
return NULL;
}
node_t *list_delete(list_t *h, int id) {
node_t *r = NULL;
if (*h && (*h)->id == id) {
r = *h;
*h = NULL;
return r;
}
// Here we have a syntax bug
node_t *p = list_find_before(h, id);
if (p) {
r = p->next;
p->next = p->next->next;
r->next = NULL;
}
return r;
}
void print_list(const list_t *h) {
node_t *p = *h;
while (p) {
printf("%d: %s says %s\n", p->id, p->name, p->msg);
p = p->next;
}
}
test_linked_list.c:
#include <stdlib.h>
#include "linked_list.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>
void test_delete_one() {
list_t h;
list_init(&h);
node_t n;
n.id = 0;
strcpy(n.name, "hello");
strcpy(n.msg, "world");
list_insert(&h, &n);
node_t *f = list_delete(&h, 0);
assert(f == &n);
}
void test_delete() {
list_t h;
list_init(&h);
node_t n[3];
int i;
for (i = 0; i < 3; i++) {
n[i].id = i;
list_insert(&h, &n[i]);
}
list_delete(&h, 1);
assert(list_size(&h) == 2);
}
void core_dump_test() {
int size = 0;
list_t h;
list_init(&h);
size = list_size(&h);
printf("list size is: %d\n", size);
}
int main() {
test_delete();
test_delete_one();
core_dump_test();
printf("Pass\n");
}
There are wrong several functions.
For example list_size
int list_size(const list_t *h) {
node_t *p = *h;
int r = 0;
do {
r += 1;
p = p->next;
} while (p);
return r;
}
can invoke undefined behavior for an empty list.
Or another example. The function list_find
node_t *list_find(const list_t *h, int id) {
node_t *p = *h;
while (p) {
if (p->id == id) return p;
p = p->next;
}
}
returns nothin in case when a specified value is not found in the list.
Or the function list_find_before
node_t *list_find_before(const list_t *h, int id) {
node_t *p = *h;
while (p && p->next) {
if (p->next->id == id) return p;
p = p->next;
}
return NULL;
}
ignores the first node of the list.
And so on.
As for the function list_delete when even in its beginning it has a bug setting *h to NULL
node_t *list_delete(list_t *h, int id) {
node_t *r = NULL;
if (*h && (*h)->id == id) {
r = *h;
*h = NULL;
return r;
}
//...
Pay attention to that nodes must be allocated dynamically. Otherwise your list does not make sense.
The reason you get a segmentation fault in core_dump_test() is list_size cannot handle an empty list: it reads p->next without checking for p != NULL. As a rule of thumb, you should avoid do/while loops as they tend to hide bugs efficiently.
Here is a modified version:
int list_size(const list_t *h) {
int r = 0;
for (const node_t *p = *h; p; p = p->next) {
r += 1;
}
return r;
}
Here are modified versions of other functions with problems:
list_find has a missing return statement:
node_t *list_find(const list_t *h, int id) {
for (const node_t *p = *h; p; p = p->next) {
if (p->id == id)
return p;
}
return NULL; // was missing
}
list_delete truncates the list if the matching node is the first one. Also the syntax bug comes from your compiler rejecting the c99 syntax.
node_t *list_delete(list_t *h, int id) {
node_t *p;
node_t *r = *h;
if (r && r->id == id) {
*h = r->next;
r->next = NULL;
return r;
}
p = list_find_before(h, id);
if (p) {
r = p->next;
p->next = r->next;
r->next = NULL;
return r;
}
return NULL; // no matching node
}

Why is the list NULL?

Why is the list NULL?
typedef struct Node
{
int elem;
struct Node* next;
} Node;
typedef struct Node* List;
List empty()
{
List l = malloc(sizeof(Node));
return l;
}
void addl(List l, int e)
{
Node *n = malloc(sizeof(Node));
n->elem = e;
n->next = l;
l = n;
}
int main()
{
List l = empty();
addl(l, 1);
addl(l, 2);
if (l == NULL)
{
printf("IS NULL");
}
return 0;
}
return → IS NULL
why ? Why not addr to the list?
I have made improvemnts and fixed some parts of your code. Compare it with yours and find your mistakes.
#include<stdio.h>
#include <stdlib.h>
struct Node
{
int elem;
struct Node *next;
};
typedef struct Node Node;
typedef struct Node *List;
List newList(int e)
{
List l = malloc(sizeof(Node));
if (l == NULL)
{
printf("IS NULL");
return NULL;
}
l->elem = e;
l->next = NULL;
return l;
}
void addl(List l, int e)
{
List n = malloc(sizeof(Node));
if(n == NULL) {
printf("Memory allocation error");
}
printf("New node: %p\n", n);
n->next = NULL;
n->elem = e;
List iter = l;
if(iter->next == NULL) {
// If there is only one node (head) in the node add the new one to the next
iter->next = n;
}
else {
while(iter->next) {
// Iterate until find the last node
iter = iter->next;
}
iter->next = n; // Finally add the new node to the end of the list
}
}
int main()
{
List l = newList(0);
addl(l, 1);
addl(l, 2);
List iterate = l;
int i = 1;
do {
printf("%d. node's element is %d\n", i, iterate->elem);
iterate = iterate->next;
i++;
if(iterate->next == NULL) {
// Catch the last node
printf("%d. node's element is %d\n", i, iterate->elem);
}
}
while(iterate->next);
return 0;
}
The output of the code:
New node: 0x8292c0
New node: 0x8296f0
1. node's element is 0
2. node's element is 1
3. node's element is 2

How to declare and access a pointer to a member of a member struct in C?

So, I am relatively new to C and trying to implement a Queue using Linked Lists. Here is some code I wrote with help from the internet.
#include <stdio.h>
#include <stdlib.h>
#define pscan(prompt, x) printf(prompt); scanf("%d", &x)
#define nl() printf("\n");
typedef struct Node {
int data;
struct Node* next;
} Node;
typedef struct LinkedList {
Node* head;
Node* tail;
int size;
int (*add) (struct LinkedList*, int, int);
int (*append) (struct LinkedList*, int);
int (*get) (struct LinkedList*, int);
int (*remove) (struct LinkedList*, int);
void (*display_list) (struct LinkedList*);
Node* (*createNode) (int);
} LinkedList;
int add (LinkedList* self, int data, int position);
int append (LinkedList* self, int data);
int get (LinkedList* self, int position);
int rmv (LinkedList* self, int position);
void display_list (LinkedList* self);
LinkedList createLinkedList ();
Node* createNode (int data);
int add(LinkedList* self, int data, int position)
{
if (position > self->size || position < 0)
{
printf("Index out of bounds\n");
return 0;
}
Node* newNode = self->createNode(data);
Node* head = self->head;
Node* tail = self->tail;
if (position == 0)
{
if (head == NULL) self->head = newNode;
else
{
if (tail == NULL) tail = head;
newNode->next = head;
self->head = newNode;
}
self->size++;
}
else if (position == self->size)
{
if (head == NULL) self->head = newNode;
else
{
if (tail == NULL) tail = head;
tail->next = newNode;
self->tail = newNode;
}
self->size++;
}
else
{
Node* prev = head;
for(int i = 0; i < position-1; i++)
{
prev = prev->next;
}
Node* node = prev->next;
prev->next = newNode;
newNode->next = node;
self->size++;
}
return 0;
}
int append(LinkedList* self, int data)
{
return self->add(self, data, self->size);
}
int get(LinkedList* self, int position)
{
if (self->size == 0)
{
printf("The list is empty.");
return 0;
}
else if (position >= self->size || position < 0)
{
printf("Index out of bound.");
return 0;
}
if (position == 0) return self->head->data;
else if (position+1 == self->size) return self->tail->data;
else
{
Node* node = self->head;
for(int i = 0; i < position; i++) node = node->next;
return node->data;
}
}
int rmv (LinkedList* self, int position)
{
int dt;
if (self->size == 0)
{
printf("The list is empty.");
return 0;
}
else if (position >= self->size || position < 0)
{
printf("Index out of bound");
return 0;
}
if (position == 0)
{
Node* head = self->head;
Node* next = head->next;
self->head = next;
dt = head->data;
free(head);
self->size--;
}
else if (position+1 == self->size)
{
Node* node = self->head;
Node* tail = self->tail;
for(int i = 0; i < self->size-2; i++) node = node->next;
node->next = NULL;
self->tail = node;
dt = tail->data;
free(tail);
self->size--;
}
else
{
Node* prev = self->head;
Node* next;
Node* node;
for(int i = 0; i < position-1; i++) prev = prev->next;
node = prev->next;
next = node->next;
prev->next = next;
dt = node->data;
free(node);
self->size--;
}
return dt;
}
void display_list(LinkedList* self)
{
if (self->size == 0) printf("This list is empty.\n\n");
else
{
Node* node = self->head;
printf("[");
for (int i = 0; i < self->size; i++)
{
if (i > 0) printf(", ");
printf("%d", node->data);
node = node->next;
}
printf("]\n\n");
}
}
Node* createNode (int data)
{
Node* node = (Node*) malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
LinkedList createLinkedList ()
{
LinkedList l;
l.head = NULL;
l.tail = NULL;
l.add = &add;
l.append = &append;
l.get = &get;
l.remove = &rmv;
l.display_list = &display_list;
l.createNode = &createNode;
l.size = 0;
return l;
}
typedef struct queue
{
LinkedList items;
int *size;
int (*enqueue) (struct queue*, int);
int (*dequeue) (struct queue*);
int (*peek) (struct queue*, int);
void (*display) (struct queue*);
} Queue;
Queue CreateQueue();
int enqueue(Queue* self, int item);
int dequeue(Queue* self);
int peek(Queue* self, int pos);
void display(Queue* self);
Queue CreateQueue()
{
Queue q;
q.items = createLinkedList();
q.size = &(q.items.size);
q.enqueue = &enqueue;
q.dequeue = &dequeue;
q.peek = &peek;
q.display = &display;
return q;
}
int enqueue(Queue* self, int item)
{
self->items.append(&(self->items), item);
return 1;
}
int dequeue(Queue* self)
{
return self->items.remove(&(self->items), 0);
}
int peek(Queue* self, int pos)
{
return self->items.get(&(self->items), pos);
}
void display(Queue* self)
{
printf("%d items in queue.\n", *(self->size));
self->items.display_list(&(self->items));
}
void main()
{
Queue q = CreateQueue();
q.enqueue(&q, 3);
q.enqueue(&q, 7);
q.enqueue(&q, 4);
q.display(&q);
int item = q.dequeue(&q);
printf("Dequeued: %d\n", item);
q.display(&q);
q.enqueue(&q, 14);
q.display(&q);
}
The part I'm having an issue with is making the Queue's size pointer point to the LinkedList's size integer and then accessing that value.
On compiling and running, I get this:
Output from the above code
Thanks in advance.
The problem is in createQueue:
Queue CreateQueue()
{
Queue q;
q.items = createLinkedList();
q.size = &(q.items.size);
q.enqueue = &enqueue;
q.dequeue = &dequeue;
q.peek = &peek;
q.display = &display;
return q;
}
You set q.size to point to q.items.size. This is a pointer to a local variable. You then return a copy of q, but the size member now points to a local that doesn't exist. Dereferencing a pointer to a variable whose lifetime has ended triggers undefined behavior.
There's no need for the size element in Queue. Just access the size element of the items member directly.

Trying to build a linked-list with strings as its entries

I'm trying to create a linked-list with strings as it data, and I have to do some opperations with them, but the opperations are cleared for integers only.
Those are the functions I've done the past weeks:
struct node {
int data;
char* s;
struct node* next;
};
typedef struct node node;
int remove_by_data(node** L, int data) {
if (*L == NULL) {
return 0;
}
node* p = *L;
if (p->data == data) {
*L = p->next;
free(p);
return 1;
}
else {
while (p->next != NULL && p->next->data != data) {
p = p->next;
}
if (p->next == NULL) {
return 0;
}
else {
node* q = p->next;
p->next = p->next->next;
free(q);
return 1;
}
}
}
node* search(node* L, int data) {
node* p = L;
while (p != NULL) {
if (p->data == data)
return p;
p = p->next;
}
return NULL;
}
int insert_end(node** L, int data) {
node* aux = malloc(sizeof(node));
if (!aux)
return 0;
aux->data = data;
aux->next = NULL;
node* p = *L;
if (p == NULL) {
*L = aux;
}
else {
while (p->next) {
p = p->next;
}
p->next = aux;
}
return 1;
}
int insert_begin(node** L, int data) {
node* aux = malloc(sizeof(node));
if (!aux)
return 0;
aux->data = data;
aux->next = *L;
*L = aux;
return 1;
}
void print_data(node* L) {
node* p = L;
while (p != NULL) { // while (p) {
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int cont(node* L, int N){
int cont=1;
node* atual= L;
while (atual != search(L, N)){
cont++;
atual = atual->next;
}
return cont;
}
void swap_node(node** L, int m, int n){
int i, t;
node* p;
node* q;
p = q = *L;
for(i=1; i<m; i++)
p = p->next;
for(i=1; i<n; i++)
q = q->next;
t = p->data;
p->data = q->data;
q->data = t;
}
I just don't know how to "convert" those functions to strings, and how can I store a string into a list

Binary tree implementation C

The 't' pointer in the insert() function is set to NULL every time I call the insert function. Is it something to do with messing up of pointers?
int main() {
int num, i;
tree *t;
t = NULL;
for(i = 0; i < 5; i++) {
scanf("%d", &num);
insert(t, num);
}
//inorder(t);
return 0;
}
The insert function is as follows:
void insert(tree *t, int num) {
int flag;
tree *p, *q;
tree *temp = (tree *)malloc(sizeof(tree));
temp->data = num;
temp->left = NULL;
temp->right = NULL;
if(t == NULL) {
t = temp;
printf("Hello");
return;
}
printf("%d", t->data);
p = t;
while(p) {
q = p;
if(p->data <= num) {
p = p->right;
flag = 1;
}
else {
p = p->left;
flag = 0;
}
if(flag == 1)
q->right = temp;
else
q->left = temp;
}
}
My tree structure is as follows :
typedef struct tree {
int data;
struct tree *left, *right;
}tree;

Resources