Creating and expanding a Linked List using Structs - c

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

Related

Linked list without struct, but using only 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;
}

How to check if a list is empty? If I do "if (ptr!=NULL)" it doesn't work [duplicate]

Usually, when I use linked lists, I write:
struct node *startPtr = NULL;
so I check later if is it NULL, and if it is, it means that the list is empty.
But in this code:
struct card{
char face[3];
char suit[4];
};
typedef struct card Card;
struct stack{
Card cardd;
struct stack *nextPtr;
};
typedef struct stack Stack;
int main(){
/*
creation of *stacks also with calloc
*/
Stack *topstacks = calloc(4,sizeof(Stack)); // array of lists initialized by calloc
/*
scanf pos1, pos2 to switch
*/
move_card(stacks, topstacks, pos1, pos2);
}
int move_card(Stack *stacks, Stack *topstacks, unsigned int pos1, unsigned int pos2){
Stack *prevfromPtr;
Stack *fromPtr = &(stacks[pos1]);
Stack *toPtr = &(topstacks[pos2]);
while(fromPtr->nextPtr!=NULL){
prevfromPtr = fromPtr;
fromPtr = fromPtr->nextPtr;
}
Stack *newmovingcard = calloc(1,sizeof(Stack));
newmovingcard->cardd = fromPtr->cardd;
newmovingcard->nextPtr = NULL;
if (toPtr!=NULL){ // here I'd like to check if the list is empty and has not any item. This way it does not work because toPtr can't be NULL, it's a pointer
while(toPtr->nextPtr!=NULL){
toPtr = toPtr->nextPtr;
}
toPtr->nextPtr = newmovingcard;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
} else {
toPtr->cardd = newmovingcard->cardd;
toPtr->nextPtr = NULL;
free(fromPtr);
prevfromPtr->nextPtr = NULL;
return 0;
}
}
I have an array of lists (topstacks), initialized with calloc. And in the commented line inside move_card, I need to check if the single list of the array of lists is empty. But I don't know how to do that.
Here is the full code, but some parts with printf are in italian, so sorry for that: https://wtools.io/paste-code/b2gz
You can try to assign nextPtr to the same element or you can introduce a special global item which will mean an empty list.
If you use malloc with memset instead of calloc you can set your value as your own "void" value.
I mean this kind of thing :
int* example;
example=malloc(100*sizeof(int)); // allocate memory to store 100 int
if(example){
memset(example,1,100*sizeof(int)); // initialize it with value 1
}
Working with two linked lists simultaneously is kind of fussy and annoying, but it is doable:
int move_card(Stack **source, Stack **target, int source_pos, int target_pos) {
// Walk through the linked list, but in every case stop one short of the
// insertion point
// Walk through the source chain and identify which pointer needs
// to be manipulated.
for (int i = 0; i < source_pos; ++i) {
if (*source == NULL) {
return -1;
}
source = &((*source)->nextPtr);
}
// Walk through the target chain and identify the insertion point.
for (int i = 0; i < target_pos - 1; ++i) {
if (*target == NULL) {
return 1;
}
target = &((*target)->nextPtr);
}
// Capture the pointer we're actually moving
Stack* moving = *source;
// Skip this link in the chain by reassigning source
*source = moving->nextPtr;
// Capture the record that's being bumped
Stack* bumped = *target;
// Reassign the target
*target = moving;
// Re-link the bumped entry back in the chain
moving->nextPtr = bumped;
return 0;
}
Where I've taken the liberty of renaming a few things to make this easier to understand. Notice how it uses a double pointer so it can manipulate the original pointers if necessary. When removing the first card from a linked list, the pointer to the "head" entry must change.
Here's a more complete "demo" harness for that code:
#include <stdio.h>
#include <stdlib.h>
struct stack {
char card[2];
struct stack *nextPtr;
};
typedef struct stack Stack;
Stack* make_stack(char face, char suit, Stack* nextPtr) {
Stack* stack = calloc(1, sizeof(Stack));
stack->card[0] = face;
stack->card[1] = suit;
stack->nextPtr = nextPtr;
return stack;
}
void print_stack(Stack* stack) {
while (stack) {
printf("%c%c ", stack->card[0], stack->card[1]);
stack = stack->nextPtr;
}
printf("\n");
}
int main(int argc, char** argv) {
Stack* source = make_stack('A', 'S', make_stack('2', 'S', make_stack('3', 'S', NULL)));
Stack* target = NULL;
print_stack(source);
move_card(&source, &target, 2, 0);
print_stack(source);
print_stack(target);
return 0;
}
Where that uses a simplified Card model.

C segfault when looping over a list

Here is my list struct:
typedef struct Header {
struct Header* next;
char empty;
int storageSize;
} Header;
And I am looping over a list to check how many elements its has:
int listSize(Header* _header) {
int count = 0;
while(_header->next) {
_header = _header->next;
++count;
}
return count;
}
And I get a segfault after reaching the end of the list.
However if I change it to:
int listSize(Header* _header) {
int count = 0;
while(_header->next) {
if(!_header->next) {
_header = _header->next;
++count;
}
else
break;
}
return count;
}
It doesn't segfault, but it also obviously doesn't count the elements right.
Change this:
while(_header->next) {
to this:
while(_header) {
since you want to loop over your list, as long as the current node is not NULL.
You were facing a segmentation fault, because you were trying to get the next data member of NULL.
It feels like you are passing an empty list to your listSize(), that is that the _header is NULL, and you are trying to get the next data member of NULL, thus a segmentation fault.
You logic is incorrect. The code should be this - and note the comments
int listSize(Header* header) {
int count = 0;
while (header) { // We have a node to count
++count; // Count it
header = header->next; // And move to the next node
}
return count;
}
In my opinion you can initialize next as 0 or *next as 0 whenever you want to create a new node.

Counting the nodes of any tree time improvement

I have to make a function which counts how many elements my tree have. My tree is not binary, is the most general kind of tree.
The node is:
typedef struct node{
char item;
int number_of_sons;
node **sons;
}
My counting function is this
void numbering(node *HT,int ok=0)
{
static int number = 0;
if (ok == 1)
{
printf("%d", number);
return;
}
if (HT == NULL)
{
return;
}
else
{
number++;
for (int i = 0;i < HT->nr_of_sons;i++)
{
numbering(HT->next[i], 0);
}
}
}
Is there a way to improve this function to make this faster?
EDIT: the way I use this function is:
int main()
{
//create tree;
numbering(tree,0);
numbering(tree,1);
}
When I call the function the second time it prints my result
You have a very strange recursive function there--you're using a static variable in the function which is never reset, so the function can only be used once per program run!
I'd rewrite it this way:
size_t nodecount(node *root)
{
size_t count = 0;
if (root)
{
count++;
for (int i = 0; i < root->nr_of_sons; i++)
{
count += nodecount(root->sons[i]);
}
}
return count;
}
If you really want to speed things up, you could augment your node structure by adding a size_t subtree_count field which you'd maintain whenever you insert or remove nodes. Another idea is to compact the pointer-to-array-of-sons into the node structure directly:
typedef struct node{
char item;
int number_of_sons;
node_t *sons[0];
} node_t;
What I've done here is made it so the sons variable is an array rather than a pointer to an array. But it has size zero (n.b. use [] or [1] if your compiler requires), because you don't know the number of sons at compile time. But you can simply allocate nodes with the right amount of space:
node_t* tree = (node_t*)malloc(sizeof(node_t) + num_sons*sizeof(node_t*));
This reduces pointer indirection by one layer, which may help performance.
Maybe this is better and more efficient:
int numbering(node *HT)
{
if (!HT)
{
return 0;
}
int num = 1;
for (int i = 0;i < HT->nr_of_sons;i++)
{
num += numbering(HT->next[i]);
}
return num;
}
I deleted your ok variable and changed the returned value from void to int.
In the case base you return 0;
For the leaf so they will return 1;
For inner nodes they will return 1 + the numbers of nodes in the
subtree.

Accessing a bit array in linked list node

I have a linked list defined as such:
typdef struct _seg
{
int bits[256]; // # of bits in bits[] array = 256
struct _seg *next; // link to the next segment
} seg;
And I was wondering how I can access the bit array inside each node of this list. If it were a regular int variable and the list was called p, I could just do p->bits = 13;. But I don't know how to get to and modify the list in this case. Can someone please help me out?
P.S. (not as important) Does anyone know what the seg; does at the very end?
To access the nodes in your list, you'll have to use a loop to iterate on all your elements:
seg* p = createList();
seg* current = p; // start at first element
while( current != NULL ){
for( int i=0; i<256; i++ ) {
current->bits[i] = 13; // modify bits inside
}
current = current->next; // go to next element in the list
}
p->bits is an array of 256 integers. You can access it with p->bits[0] = 13.
Or in general p->bits[i] = 13 where 0 <= i < 256.
typdef struct _seg
{
...
}seg;
With this you can define a variable of this struct type using seg as
seg SomeName;
No need for struct _seg someName;.

Resources