c linked list append insert - c

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)++;
}

Related

How to reduce runtime from linear to constant?

lengthOfLinkedList() below counts the number of nodes in a linked list, but the runtime is linear which I do not want. How can I reduce it to a constant runtime function? Are there any library functions I can use?
typedef struct node {
int val;
struct node *next;
} NODE;
struct list_struct {
NODE *front;
NODE *back;
};
int lengthOfLinkedList(LIST *l) {
NODE *n = l->front;
int count = 0;
while (n != NULL) {
count++;
n = n->next;
}
return count;
}
You cannot achieve constant time size calculation with your current struct definition. Now, if you add a size_t member to the struct and use it to store the length, modifying it on any additions or deletions, you can access the length in constant time.
typedef struct node {
int val;
struct node *next;
size_t length;
} NODE;
Define the head-node struct accordingly.
For int value type the list-node remains same:
typedef struct _node {
int val;
struct _node* next;
} listNode_t;
We alter the head-node to suit our needs:
typedef struct {
// add members as scenario demands
int size; // updated after every insert/delete
int min; // updated/checked after every insert/delete/update
int max; // updated/checked after every insert/delete/update
long sum; // updated after every insert/delete/update
listNode_t* first; // to insert/delete from beginning (LIFO-Stack)
listNode_t* last; // to insert at the end (can't delete though)
} listHead_t;
Then you can get those values in O(1), provided they're updated consistently.
listHead_t* head;
...
int listLength = list_getSize (head);
int listMin = list_getMin (head);
int listMax = list_getMax (head);
long listSum = list_getSum (head);
float listAvg = list_getAverage (head); // (float)sum/size
/* List Methods */
list_prefix (head, value); // add value as the first node
list_suffix (head, value); // add value as the last node
That makes list_prefix() like:
...
#include <limits.h>
...
listHead_t* head = list_init_head ();
...
...
listHead_t* list_init_head () {
listHead_t* head = malloc (sizeof(listHead_t));
if (!head) {
perror("list_init_head-malloc");
exit (1);
}
head->size = head->sum = 0;
head->first = head->last = NULL;
head->min = INT_MAX;
head->max = INT_MIN;
return head;
}
int list_prefix (listHead_t* head, int val) {
if (!head) return -1; // invalid call
listNode_t* node = malloc (sizeof(listNode_t));
if (!node) {
perror("list_prefix-malloc");
exit (1);
}
node->val = val;
// update list-head stats
++head->size;
head->sum += val;
if (val < head->min) head->min = val;
if (val > head->max) head->max = val;
if (!head->first) {
node->next = NULL;
head->first = head->last = node;
} else {
node->next = head->first;
head->first = node;
}
return 0;
}

How to loop over a linked-list in c

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.

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

i want to implement separate chaining hashing in c. but the code is running out of memory in the createhashtable function

#include<stdio.h>
#include<stdlib.h>
#define LOADFACTOR 5
struct listnode
{
int key;
int data;
struct listnode *next;
};
struct hashnode
{
int bcount; //block count
struct listnode *next;
};
struct hashtable
{
int size;
int count;
struct hashnode **table;
};
struct hashtable * createhashtable(int s)
{
struct hashtable * h = (struct hashtable*)malloc(sizeof(struct hashtable));
//if(!h)
//retur
h->size = s/LOADFACTOR;
h->count = 0;
h->table = (struct hashnode **)malloc(sizeof(struct hashnode *) * (h->size));
if(!h->table)
printf("memory erroe");
int i;
for(i=0;i< h->size;i++)
{
printf("a");
h->table[i]->next = NULL;
h->table[i]->bcount =0; giving error in this for loop
}
return h;
}
int hash(int size , int item)
{
int index = item %size;
return index;
}
int hashsearch(struct hashtable * h , int item)
{
struct listnode *temp = NULL;
temp = h->table[hash(h->size,item)]->next;
while(temp)
{
if(temp->data == item)
return 1;
temp = temp->next;
}
return 0;
}
int insertintohash(struct hashtable *h , int item)
{
int index;
struct listnode * newnode ,*temp;
if(hashsearch(h,item))
return 0;
index = hash(h->size,item);
temp = h->table[index]->next;
newnode = (struct listnode *)malloc(sizeof(struct listnode));
if(!newnode)
{
printf("out of space");
return -1;
}
newnode->key = index;
newnode->data = item;
newnode->next = h->table[index]->next;
h->table[index]->next = newnode;
h->table[index]->bcount++;
h->count++;
return 1;
}
int main()
{
struct hashtable * h = NULL;
h = createhashtable(60);
if(insertintohash(h,5))
printf("successfully inserted");
return 0;
}
the createhashtable function is giving run time error while assinging every hashtable node next pointer to NULL
the for loop used in the createhashtable is giving run time error please just me a solution
h->table is pointer to pointer to struct hashnode. You allocated a
list of 12 pointers to struct hashnode. These pointers are not
initialized. You need to do this first inside the loop:
h->table[i] = malloc(sizeof(struct hashnode));
With suitable error checking, of course.

Using a for loop to create a linked list [duplicate]

This question already has answers here:
Creating a linked list with a for loop
(2 answers)
Closed 9 years ago.
Newb C programmer here, assuming I have a struct for a node as follows
struct node{
int data;
struct node *next;
};
How would I use a loop to make a linked list where the first node's data is 0, and a pointer to the next node whose data is 1. etc.
EDIT:
int main(int argc, char* argv[]){
struct node a;
a.data = 0;
struct node * tempnode = &a;
for (int i = 1; i < 5; i++){
struct node * next;
next->data = i;
tempnode->next = next;
tempnode = next;
}
Heres what i tried but it doesn't work
This might help..
#include<stdio.h>
#include<stdlib.h>
// Prototypes
void InitList(struct list *sList);
void push(struct list *sList, int data);
void pop(struct list *sList);
void print(struct list *sList);
/* Node Structure */
struct node {
int data;
struct node *next;
};
/* List Structure */
struct list {
struct node *start;
};
int main(int argc, char** argv)
{
int x;
struct list MyList;
InitList(&MyList);
for(x = 0; x < 100; x++) push(&MyList, x);
print(&MyList);
printf("\n");
for(x = 0; x < 25; x++) pop(&MyList);
print(&MyList);
printf("\n");
for(x = 0; x < 80; x++) pop(&MyList);
print(&MyList);
printf("\n");
return 0;
}
/* Initializes the list structure */
void InitList(struct list *sList)
{
sList->start = NULL;
}
/* Adds a value to the front of the list */
void push(struct list *sList, int data)
{
struct node *p;
p = malloc(sizeof(struct node));
p->data = data;
p->next = sList->start;
sList->start = p;
}
/* Prints the list */
void print(struct list *sList)
{
struct node *p = sList->start;
while(p != NULL) {
printf("%d ", p->data);
p = p->next;
}
}
/* Removes the first value of the list */
void pop(struct list *sList)
{
if(sList->start != NULL) {
struct node *p = sList->start;
sList->start = sList->start->next;
free(p);
}
}
You are not allocating memory to store your struct data. Here's how you can do it
for(int i = 1; i < 5; i++) {
struct node *next = malloc(sizeof *next); // allocate memory to store the struct
next->data = i;
tempnode->next = next;
tempnode = next;
}

Resources