Linked list without struct, but using only arrays - arrays

#include <stdio.h>
int main()
{
int n, i;
int head = 0;
printf("No of Students:\n");
scanf("%d", &n);
int data[n];
int address_of_data[n];
int *next;
printf("Enter Marks:\n");
for (i = 0; i < n; i++)
{
scanf("%d", &data[i]);
}
for (i = 0; i < n; i++)
{
if (data[head] != -1)
{
address_of_data[head] = &data[i];
}
else
{
break;
}
head++;
}
next = address_of_data[0];
for (i = 0; i < n; i++)
{
printf("%d ", *(next + i));
}
return 0;
}
In the above code, I used pointers to print the data values. Using two arrays, one for the data and another for the address of the data. But I don't how to actually implement a linked List out of this, I am really confused, can anyone tell how to implement a Linked-List without using structures.

The key advantage of a linked list is that when you insert or append an element, you can store that element anywhere in memory. Other elements in the list can point to it, and if you iterate over the list, you jump back and forth anywhere in memory following the pointers down the chain formed by the elements, until you reach the tail, which has a null pointer because it is the last element.
Implementing a linked list 'using only arrays' does not really make much sense. Even if you could, why would you want to? Arrays are great because you can index directly into them in constant time - you can't do this with linked lists, you can only iterate over them. But arrays have their drawbacks too - they are fixed size, and when they fill up, they fill up! Most shared library lists like the ArrayList in Java or the vector class in C++ store the underlying data in a fixed size array, and then if you insert too many items for that array, they create a new, larger array behind the scenes and copy the elements across for you. There really is no magic solution for when you run out of room in your array.
So with that being said, why would you implement a linked list using only arrays? You remove their only advantage - that you can append arbitrarily without costly reallocations. I'm not even sure if it's a well defined question. Perhaps if you're really desperate, you can create one large array and treat it like your own virtual memory, allocating and freeing slots in it, and then treat a two element array as an entry (entry[0] = data, entry[1] = 'address' of next, i.e. an index into your large array). But this smacks of terrible code and is really missing the point of linked lists.

Here is a complete example of a simple linked list - for more ease in pure C. Note the "next" member in the structure - this is a pointer to the successor in the list.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct MY_DATA {
int number;
char info[30];
struct MY_DATA *next;
};
#define MAX_ELEMS 5
int main(int argc, char **argv)
{
struct MY_DATA *root = NULL; /* Root of list */
struct MY_DATA *prev = NULL; /* Previously created element */
for(int i = 0; i < (MAX_ELEMS); i++)
{
/* Allocate memory ... */
struct MY_DATA *new_data = (struct MY_DATA *)malloc(sizeof(MY_DATA));
/* ...and inialize new data set */
memset(new_data, 0x00, sizeof(MY_DATA));
new_data->number = i * i;
sprintf((char *)&(new_data->info), "This is data record %d", i);
if (root == NULL)
{
root = prev = new_data; /* Remember the first element */
}
else
{
prev->next = new_data; /* The previous element has now a successor */
prev = new_data; /* Remember this for next iteration */
}
}
struct MY_DATA *current = root; /* Get the 1st element in the list */
struct MY_DATA *temp = NULL; /* Just for clean up stuff */
for(int i = 0; i < (MAX_ELEMS); i++)
{
/* Display data */
printf("Data set #%d: %s\n", current->number, current->info);
temp = current; /* This becomes deleted */
current = current->next; /* Set current pointer to successor of current element */
free(temp);
}
return 0;
}
Another exampe - accessing an array with indexes or pointers:
#include <stdio.h>
#define MAX_ELEMS 5
int my_array[MAX_ELEMS] = { 5, 18, 42, 31, 10 };
int main(int argc, char **argv)
{
int *current = (int *)my_array; /* Get the 1st element in the list */
for(int i = 0; i < (MAX_ELEMS); i++)
{
/* Using array index */
printf("Data set #%d \n" \
" Indexed access: %d\n", i, my_array[i]);
/* Using the pointer*/
printf(" Pointer access: %d\n", *current++);
}
return 0;
}

Related

Singly linked list create function C

I am currently trying to make function create() for singly linked list, where I am supposed to pass unlimited amount of parameters and it will pass the parameters as nodes' values. The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//define sllnode struct
typedef struct sllist
{
int val;
struct sllist *next;
}
sllnode;
sllnode* create(int count, ...);
int main(void)
{
//here i try to print out values of this list
sllnode* new_sllist = create(34,2,5,18);
//print out values that I have assign using create() to test
for(int i = 0; i < 4; i++)
{
printf("%i\n",new_sllist[i].val);
}
}
//create function
sllnode* create(int count, ...)
{
va_list list;
int i;
int arr[count];
va_start(list, count);
//create array arr that have all the values passed as parameters
for(i = 0; i < count; i++)
{
arr[i] = va_arg(list,int);
}
//allocate memory for new singly linked list
sllnode *sllist = malloc(count * sizeof(sllnode));
//check if memory has been successfully allocated
if(sllist == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// loop through array arr and assign values to val and *next of each sllnode in new sllist
for (int j = 0; j < count; j++)
{
sllist[j].val = arr[j];
sllist[j].next = &sllist[j+1];
if(j == count - 1)
{
sllist[j].val = arr[j];
sllist[j].next = NULL;
}
}
return sllist;
free(sllist);
}
But when I print out I only receive the last 3 values (2,5,18) and a number -23791193490 which differs each time (I suppose this has seeped into another part of memory). How do I do this correctly?
You are passing 34 for the count parameter. Correct usage would be:
sllnode* new_sllist = create(4,34,2,5,18);

Segfaults on commented lines :

I'm trying to solve a problem on Codechef. I've posted about this before but am doing in completely differently.
http://www.codechef.com/problems/STEPUP#
The idea of the problem is to determine whether or not the desired situation arises for the given testcase.
A desired situation is when every vertex has a higher indirection than the vertices that are connected to it. Ie. if a->b, F(b) should be > F(a). If this isn't possible for the given setup, output is IMPOSSIBLE. If not, output the minimum value of F(x) for the vertex X with maximum indirection such that it holds for all other vertices.
I haven't tried to print the output for the possible cases yet.
INPUT FORMAT:
First line of input contains a number t, the number of test cases.
Each test case contain starts with two space seperated integers N and M, denoting the number of vertices and the number of edges in the graph respectively.
Each of the following M lines contain two space seperated integers a b denoting an edge from vertex a to vertex b.
There can be multiple edges between two vertices a and b.
For eg.,
2
2 2
1 2
2 1
3 2
1 2
1 3
OUTPUT should be:
IMPOSSIBLE
2
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Node{
int val;
struct Node* next;
};
int indirection[10001];//indirection[a] holds count. What vertex it holds count OF is given by list[a].val;
int main()
{
int testcases, num_vertices, num_edges, a,b,c,d,e;
scanf("%d", &testcases);
while(testcases--)
{
scanf("%d %d",&num_vertices, &num_edges);
struct Node *list[num_vertices];//array of pointers to node
int h;
struct Node * ptr;
for(h=1;h<=num_vertices;h++)
{
list[h]=(struct Node *)malloc(sizeof(struct Node));
list[h]->val=0;
}
memset(indirection,0,10001);
for(e=0;e<10001;e++)
printf("Indirection[e]=%d \n",indirection[e]);
a=1;
while(a<=num_edges)
{
printf("messge printing for the %dth time\n",a);
scanf("%d %d",&b,&c);
printf("Message recd %d \n",indirection[c]);
if(indirection[c]==0)
{
printf("entered case1\n");
list[a]->val=c;
printf("S\n");
//Segfaults here
list[a]->next->val=b;
printf("SS\n");
indirection[a]=1;
ptr=list[a]->next;
printf("SSS \n");
printf("case1\n");
}
else
{ printf("entered case2\n");
indirection[c]++;
//segfaults here if i comment out the previous one
ptr->next->val=b;
printf("case2\n");
ptr=ptr->next;
}
a++;
}
int tra,i;
struct Node *ptr1,*ptrnext;
for(i=1;i<=num_edges;i++)
{
ptr1=list[i];
ptrnext=list[i]->next;
{
if (indirection[ptr1->val]<indirection[ptrnext->val])
{ printf("IMPOSSIBLE");
break;
}
else
{
ptr1=ptrnext;
ptrnext=ptrnext->next;
}
}
}
free(list);
}
}
The 2 statements where I've mentioned a segfault in comments are just before the (I think) questionable statements. If I remove the first, segfault at the second. If I remove both, segfault ANYWAY.
Still trying to solve this problem so I can move forward with the next one. Thanks!
num_vertices treated as if it is 1 based rather than 0 based
struct Node *list[num_vertices];//array of pointers to node
int h;
struct Node * ptr;
// for(h=1;h<=num_vertices;h++)
for(h=0;h<num_vertices;h++)
{
list[h]=(struct Node *)malloc(sizeof(struct Node));
list[h]->val=0;
}
next field is not initialized as answered by Daniel
{
list[h]=(struct Node *)malloc(sizeof(struct Node));
list[h]->val = 0;
list[h]->next = something_maybe_NULL();
}
Suggest simpler malloc() style
list[h] = malloc(sizeof *(list[h]));
Your code segfaults because you create an array of struct Node* and allocate memory for them, but you never set the next pointer of each Node. So each Node's next pointer is just pointing somewhere random in memory and segfaults when you try to access it.
I think your design is just wrong. If you are trying to make a linked list of nodes (as suggested by the presence of a next pointer), you don't need to create an array to hold the nodes at all.
I analyzed all your code and found several problems in it, these problems indicate mainly that you don't understand pointers
Arrays are 0-index based
/* if you declare, struct list[size];
* index goes from 0 ti szie - 1
*/
for (h = 1 ; h <= num_vertices ; h++)
{
You never initialize node->next pointer
/* You should initialize the next node to null. */
list[h]->next = NULL;
Your memset is wrong, sizeof(int) != 1
/* memset(indirection, 0, 10001); wrong */
memset(indirection, 0, 10001 * sizeof(int));
You don't check for overflow when accessing the indirection array
/* this is very unsafe, you don't check c */
printf("Message recd %d \n", indirection[c]);
You dereference node->next without checking for NULL
/* don't dereference list[a]->next without checking .
* list[a]->next->val (wrong)
*/
next = list[a]->next;
if (next != NULL)
next->val = b;
You free list, it is an array not a pointer so you can't call free on it, however, you should free its elements, since they are pointers to valid malloced memory
for (i = 0 ; i < num_vertices ; i++)
free(list[i]);
Here is a version of your code with this issues fixed, I don't know if your algorithm works, but the code has at least 6 fewer errors.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* no need for typedef, since you declare as struct Node */
struct Node
{
int val;
struct Node* next;
};
int indirection[10001];//indirection[a] holds count. What vertex it holds count OF is given by list[a].val;
int main()
{
int testcases, num_vertices, num_edges, a, b, c;
printf("input testcase: ");
scanf("%d", &testcases);
while (testcases--)
{
printf("input testcase num_vertices and num_edges: ");
scanf("%d %d",&num_vertices, &num_edges);
int h;
struct Node *list[num_vertices]; // array of pointers to node
struct Node *ptr;
/* struct list[size];
* index goes from 0 ti szie - 1
*/
for (h = 0 ; h < num_vertices ; h++)
{
/* If this is plain C you don't need the cast (struct Node *) */
list[h] = malloc(sizeof(struct Node));
list[h]->val = 0;
/* You should initialize the next node to null. */
list[h]->next = NULL;
}
/* memset(indirection, 0, 10001); wrong */
memset(indirection, 0, 10001 * sizeof(int));
/* What, you dont believe all values are 0? */
/* for(e = 0 ; e < 10001 ; e++)
printf("Indirection[e] = %d\n",indirection[e]); */
/* arrays go from 0 ti size - 1 */
a = 0;
while (a < num_edges)
{
printf("messge printing for the %dth time\n", a);
printf("input b and c: ");
scanf("%d %d", &b, &c);
if (c < 10001)
{
/* this is very unsafe, you don't check c */
printf("Message recd %d \n", indirection[c]);
if (indirection[c]==0)
{
struct Node *next;
printf("entered case1\n");
list[a]->val = c;
printf("S\n");
// Segfaults here
/* don't dereference list[a]->next without checking . */
next = list[a]->next;
if (next != NULL)
next->val = b;
printf("SS\n");
indirection[a] = 1;
ptr = list[a]->next;
printf("SSS \n");
printf("case1\n");
}
else
{
printf("entered case2\n");
indirection[c]++;
//segfaults here if i comment out the previous one
ptr->next->val=b;
printf("case2\n");
ptr=ptr->next;
}
a++;
}
}
int i;
struct Node *ptr1, *ptrnext;
for(i = 0 ; i < num_edges ; i++) /* arrays go from 0 ti size - 1 */
{
ptr1 = list[i];
if (ptr1 != NULL)
ptrnext = ptr1->next;
if ((ptr1 != NULL) && (ptrnext != NULL))
{
if (indirection[ptr1->val] < indirection[ptrnext->val])
{
printf("IMPOSSIBLE");
break;
}
else
{
ptr1 = ptrnext;
ptrnext = ptrnext->next;
}
}
}
for (i = 0 ; i < num_vertices ; i++)
free(list[i]);
}
return 0;
}
in your code
list[a]->next->val=b;
list[a]->next maybe NULL. IMO, it's better to put a NULL check before dereferencing.
Same goes for ptr->next in
ptr->next->val=b;
Nevertheless, you need to allocate memory to next before using it. Otherwise, it will point to some
unknown memory location.
Also, why not start the loop from 0 in
for(h=1;h<=num_vertices;h++)
Sidenote: Please do not cast the return value of malloc().

Doubling an array that points to a linked list in C

I am implementing a hashset in C, where my array points to a linked list
this is the linked list:
typedef struct hashnode hashnode;
struct hashnode {
char *word;
// will hold our word as a string
hashnode *link;
//will be used only if chaining
};
and this is the Hashset:
struct hashset {
size_t size;
//size of entire array
size_t load;
//number of words total
hashnode **chains;
//linked list (if words have same index);
};
Now I am having a problem with my double array code
I believe there is a dangling pointer somewhere
here is the code:
void dbl_array(hashset *this) {
size_t newlen = this->size +1;
newlen *= 2;
//double siz
hashnode **new_array = malloc(newlen * sizeof(hashnode*));
//new array
int array_end = (int)this->size;//load;
//end of old array
for(int i = 0; i < array_end; i++) {
//loop through old
int index = i;
if(this->chains[index] == NULL) {
continue;
}
else {
hashnode *nod;
int i=0;
for(nod = this->chains[index]; nod != NULL; nod = nod->link) {
if(nod == NULL)
return;
size_t tmp = strhash(nod->word) % newlen;
//compute hash
hashnode *newnod;
newnod = malloc(sizeof(hashnode*));
newnod->word = strdup(nod->word);
newnod->link = NULL;
if(new_array[tmp] == NULL) {
//if new array does not already have a word at index
new_array[tmp] = newnod;
}
else {
//if word is here then link to old one
newnod->link = new_array[tmp];
new_array[tmp] = newnod;
}
printf("newarray has: %s # {%d} \n", new_array[tmp]->word, tmp);
//testing insertion
i++;
}
free(nod);
}
}
this->chains = new_array;
this->size = newlen;
free(new_array);
printf("new size %d\n", this->size);
}
So after running GDB, I am finding that there is something wrong when I add the new node
There is no reason at all to allocate new collision nodes for a hash table expansion. The algorithm for expanding your hash table is relatively straight forward:
compute new table size
allocate new table
enumerate all chains in old table
for each chain, enumerate all nodes
for each node, compute new hash based on new table size
move node to appropriate slot in new table
When the above is done, so are you. Just wire up the new table to the hashset and make sure to update the size member to the new size. The old table is discarded.
The following code assumes you have properly managed your hash table prior to doubling. With that:
All unused table slots are properly NULL
All collision lists are properly NULL-terminated.
If you can't guarantee both of those conditions, doubling the size of your hash table is the least of your worries.
void hashset_expand(hashset* hs)
{
size_t new_size = 2 * (1 + hs->size), i, idx;
hash node *next, *nod, **tbl = calloc(new_size, sizeof(*tbl));
// walk old table, and each chain within it.
for (i=0; i<hs->size; ++i)
{
next = hs->chains[i];
while (next)
{
nod = next;
next = next->link; // must be done **before** relink
idx = strhash(nod->word) % new_size;
nod->link = tbl[idx];
tbl[idx] = nod;
}
}
// finish up, deleting the old bed.
free(hs->chains);
hs->chains = tbl;
hs->size = new_size;
}
That is all there is to it. Don't make it more complicated than that.

Creating and expanding a Linked List using Structs

I have been working on a program in C99 which is based heavily around structs. I found that I could create linked lists of structs, and thought to give it a try.
The following is a miserable attempt, reworked about 50 times, that is meant to do the following:
1) Create a struct of type BASE in the main method, which contains the head of a linked list (CHAIN).
2) Pass this BASE struct to another function, which will append additional CHAIN elements to the end of the linked list.
3) Print the linked lists elements in main, as proof to myself that the changes are not just in the other method.
#include <stdlib.h>
#include <stdio.h>
typedef struct Base {
//many things
struct Chain *head;
} BASE;
typedef struct Chain {
int x;
struct Chain *next;
} CHAIN;
void extendChain(BASE *Data, int length);
int main() {
BASE Data;
CHAIN *pointer;
Data.head = 0;
int length = 10; //userInput(); // gets integer
extendChain(&Data, length);
pointer = Data.head;
while (pointer) {
printf("%d\n", pointer->x);
pointer = pointer->next;
}
}
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
for (int i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
position = malloc(sizeof(CHAIN));
position->next = 0;
position->x = i; // placeholder
}
}
}
This has turned out terribly, and I realize that my example doesn't begin to work even in theory (but I gave it my best shot). I'm beginning to think that the only way to do this is if I do it all in the same method, which I successfully managed to do earlier, however this will quickly become messy, and a method would definitely be best.
Does anyone have a creative way of adding X elements to a linked list when passed only a struct containing the header of this linked list? Much appreciated, as always.
Logical errors in your code. This code worked:
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
int i;ยท
for (i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
Data->head->next = NULL; // <=========
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
CHAIN * position_new_node = malloc(sizeof(CHAIN)); // <=========
position_new_node->next = 0; // <=========
position_new_node->x = i; // placeholder // <=========
position->next = position_new_node; // <=========
}
}
}
Algorithm
Create the original linked list
Send the linked list to be added, to the function
Traverse till the end of first linked list (Let the pointer be t)
repeat:
node next to t=next node of new linked list
move both nodes one unit forward
till the next node of new linked list is Null

C - String Linked List

I need to take the following code, and modify it to accept strings as arguments, instead of ints. In the end, I need the program to take all command line arguments, and add them to a linked list of strings.
So if the input was six seven eight, when i printed the linked list, it would print: eight seven six.
#include <stdio.h>
#include <stdlib.h>
typedef struct iNode
{
int myInt;
struct iNode* next;
} IntNode, *IntNodePtr;
IntNodePtr insert(int i, IntNodePtr p)
{
IntNodePtr newp = malloc(sizeof(struct iNode));
newp->myInt = i;
newp->next = p;
return newp;
}
printlist(IntNodePtr p)
{
if(p == NULL)
printf("\n");
else
{
printf("%d ", p->myInt);
printlist(p->next);
}
}
main(int argc, char* argv[])
{
int n = 5;
if(argc > 1)
n = atoi(argv[1]);
IntNodePtr iNodeList;
iNodeList = NULL;
int i = 0;
while(i < n)
{
iNodeList = insert(i++, iNodeList);
printf("List is now: ");
printlist(iNodeList);
}
}
If printing the solution backwards is the problem, just maintain a global head ptr that points at the first iNode. When you have to print, while(headPtr.next !=null){ printf(...); }
I think your question relates to the order of items in the list.
Consider that, with linked lists, it is possible to add items to the head, to the tail, or insert them at an arbitrary place.
Look at the insert() function, it adds new items where?
Simplistically, you can just reverse the order in which you insert items. In real life that probably won't go down too well.
Maybe maintain a tail pointer?
And write an addItemToTail() function?
You should read more about pointers and memory. Good place to learn that is Stanford CS Education Library. You'll find there also nice materials about linked lists.

Resources