c - Implementation of queue using linked list - c

I tried to do implementation of queue by using linked list, but there always occurred error: incompatible types in assignment and assignment makes pointer from integer without a cast.
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include "Queue.h"
struct QUEUE_ELEMENT{
int element;
struct QUEUE_ELEMENT *next;
};
int size;
struct QUEUE_ELEMENT *head, *tail;
void initQueue(){
head = NULL;
tail = NULL;
size = 0;
} // void initQueue()
int queueEmpty(void) {
return (head == NULL && tail == NULL);
} // int queueEmpty(void)
int enqueue(QUEUE_ELEMENT e) {
struct QUEUE_ELEMENT *temp;
if (tail == NULL){
tail -> next = NULL;
tail -> element = e;
head = tail;
}
else {
temp = malloc(sizeof(QUEUE_ELEMENT));
tail -> next = temp;
temp -> element = e;
temp -> next = NULL;
tail = temp;
}
return size++;
} // int enqueue(QUEUE_ELEMENT e)
int dequeue(QUEUE_ELEMENT *e){
struct QUEUE_ELEMENT *temp;
temp = malloc(sizeof(QUEUE_ELEMENT));
if (queueEmpty() != 0 ){
temp = head;
if(temp -> next != NULL){
temp = temp -> next;
free(head);
head = temp;
}
else{
free(head);
head = NULL;
tail = NULL;
}
}
return size--;
} // int dequeue(QUEUE_ELEMENT *e)
I revised my code a lot.
Why 'tail -> element = e;' in enqueue() occurs error 'incompatible types in assignment'? How can I fix it?

Is it a homework or for a real need? For the first one I won't say anything. But if you need it in practice, it's better to use already implemented solution.
There is a popular style where, in a linked list, head looks like a usual entry and the only thing which distinguishes it is the head pointer value itself. The first good example is Linux linked lists implementation (a description). Its specifics is a trick to get the whole entry address from its link member. This one is trivial to study and can answer your goals immediately.
The second good example is BSD list and queue macro set (a manpage; particularly, you could start with TAILQ macro set). It's more cumbersome due to some tricks (e.g. forward pointers address link field but backward pointers address the whole structure) but still efficient.
I hope both can satisfy you and prevent reinventing a wheel :)

You are assigning tail->element, which is an int, to e which is a QUEUE_ELEMENT. if you want to access the element in e you have to deference it like you did with tail first.
so tail->element = e->element

Related

How can i create multiple linked lists in C for same types of data?

struct clist {
int pos;
char* color;
struct clist *next;
};
typedef struct clist sl_clist;
sl_clist *head = NULL;
sl_clist* link[5];
So i am trying to create multiple single linked circular lists and put them into a stack, every list will have the same types of data. In this case i am using the stack as an array. But i just cannot figure out how to create multiple linked lists from single type. I am a student so i am not very experienced on C. Thaks for the help in advance.
void create_list (int N, sl_clist* head){
int i;
sl_clist *new;
sl_clist *old;
if(N == 0){
head = NULL;
}
srand(time(0));
for(i = 0; i < N; i++){
new = (sl_clist*)malloc(sizeof(sl_clist));
if(i == 0){
head = new;
new -> color = color[(rand()%10)];
new -> pos = pos[i];
new -> next = head;
}
else{
new -> color = color[(rand()%10)];
new -> pos = pos[i];
old -> next = new;
new -> next = head;
}
old = new;
}
}
I have also tried creating multiple "head" variables but for some reason when i use them in this function(just imagine there are arrays for color and pos) they always return NULL.
Do not use global variables. Remove them.
sl_clist *head = NULL;
sl_clist* link[5];
Using local varaibles will "force" you to use a modular design that supports multiple lists.
Variables are passed by value:
head = new;
modifies a copy sl_clist* head of the original pointer passed as the argument. The original pointer is unaffected.
There are multiple ways you can solve that problem. You can return the new value:
sl_clist *create_list (int N, sl_clist* head){
...
return new; // or old value
}
int main() {
sl_clist *head = NULL;
head = create_list(5, head);
}
You can take the pointer by reference:
int create_list (int N, sl_clist **head){
...
*head = new; // set new value
(*head)->something = something; // be aware of operator precedence
}
int main() {
sl_clist *head = NULL;
create_list(5, &head); // head is getting modified
}
But I recommend doing a separate type for the head. That way the function is clear - it takes the head, specifically, not any list element. Be verbose:
struct sl_head {
struct clist *head;
};
int create_list(int N, struct sl_head *head) {
// ^^^^^^^^^^^^ - verbose, this is the head, not some element, less mistakces
head->head = new; // a bit more to type
head->head->something = something;
}
int main() {
struct sl_head head = {0}; // no longer a pointer
create_list(5, &head); // head is getting modified
}
Move srand(time(0)); to main(). It's not a function that you call when creating a list.

How would you iterate this 2D linked list?

How would you iterate this 2D linked list?
typedef struct _NODE
{
char *pszName;
unsigned long ulIntVal;
char *pszString;
struct _NODE *pNext;
struct _NODE *pDown;
} NODE;
I could do something like this..
NODE *pHEad;
while (pHead != NULL) {
printf("%s", pHead->pDown->pszName);
pHead = pHead->pNext;
}
.. but it would only give me the one node under every next node. What if it is another node under that one again? And under that one again? Or if there is a pNext attached to the pDown?
In the simplest case, you could use something like the following recursive function:
void processNode(NODE *current) {
if (current != NULL) {
printf("%s", current->pszName);
processNode(current->pNext);
processNode(current->pDown);
}
}
int main(void) {
NODE *pHead;
/* ... Do something to fill your list ... */
processNode(pHead);
/* ... */
}
Also be aware that this can cause a deep nesting of the function calls depending on your processed list. So if you are on an embedded system with limited stack size or if you are processing huge lists, you might run out of stack. In that case, you should find another approach for the processing.
Note that this will first process the pNext-list and then start with processing the first node of the pDown-list of the last node. So assuming the following structure (to the right is pNext and downwards is pDown):
pHead -> p1 -------> p2
|- p1_1 |- p2_1 -> p2_1_1
\- p1_2 |- p2_2
\- p2_3 -> p2_3_1
it should print the nodes in the following order:
pHead, p1, p2, p2_1, p2_1_1, p2_2, p2_3, p2_3_1, p1_1, p1_2
Look at this answer. Don't be overwhelmed by the amount of the code. I have added enough comments to help you proceed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node{
char data[100]; // Assume that this linked list will contain only 100 chars of data
struct Node* next;
} NODE;
// Global Variables are bad, but oh well.
NODE* head = NULL;
// Function to create a node
NODE* createNode(char* str)
{
// First allocate memory for struct
NODE* newNode = malloc(sizeof(NODE));
if(newNode == NULL)
{
printf("Unable to create a new node.");
}
else
{
// Use strcpy or strncpy or memcpy instead of doing something like newNode -> data = str, which changes the pointer, but doesn't copy the contents
// That is do not do newNode -> data = "hello" or something
strncpy(newNode -> data, str, strlen(str));
newNode -> next = NULL;
}
return newNode;
}
void addNode(char* str)
{
// Returns a node which contains str, but points to NULL
NODE* newNode = createNode(str);
// If the linked list is empty, then we make this node itself as the first node(or head)
if(head == NULL)
{
head = newNode;
}
// Else if the linked list is not empty, then we add this node at the start of the linked list
else
{
newNode -> next = head;
head = newNode;
}
}
int main()
{
// Example Linked List Generated(say you already have it in some form)
addNode("This");
addNode("Is");
addNode("Linked List");
// Now let's print the linked list
// Temporary NODE pointer ptr is used in order to not mess with the original NODE pointer head.
NODE* ptr = head;
// Traverse through the linked list starting from head and at the same time printing the corresponding data, until ptr is null
// This ptr != NULL check is exactly what you are looking for. This is your way of stopping the traversal of Linked List once you
// are at the end of it. You don't have to know the number of nodes to stop the traversal this way.
while(ptr != NULL)
{
printf("%s ", ptr -> data);
ptr = ptr -> next;
}
}
However note that the output will be printed in reverse order, since in this implementation of linked list we are adding things towards the back. Just try running the program and start reading the program starting from main function. I have made the code into separate functions to make it easier for you to understand. Just run the code first to get a grasp of what's happening.
You can use iteration instead of recursion by adding a queue, too, if you want to avoid the possibility of a stack overflow—though this will use slightly more heap memory, and there is still a risk that you can run out of heap memory if you have a large list or if you're running on a memory-constrained system. The important part is the print_list function at the end; the other stuff is just a (mostly) self-managing queue implementation I've provided:
typedef struct node_queue NodeQueue;
struct node_queue {
NODE *n;
NodeQueue *next;
};
/*
* Add an item to the end of the queue.
*
* If the item could not be added, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int enqueue(NodeQueue **headp, NodeQueue **endp, NODE *n)
{
NodeQueue *old_end = *endp;
NodeQueue *new_end;
new_end = malloc(sizeof *new_end);
if (new_end == NULL) {
return 0;
}
new_end->n = n;
new_end->next = NULL;
if (old_end != NULL) {
old_end->next = new_end;
}
if (*headp == NULL) {
*headp = new_end;
}
*endp = new_end;
return 1;
}
/*
* Remove an item from the head of the queue,
* storing it in the object that "nret" points to.
*
* If no item is in the queue, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int dequeue(NodeQueue **headp, NodeQueue **endp, NODE **nret)
{
NodeQueue *old_head = *headp;
NodeQueue *new_head;
if (old_head == NULL) {
return 0;
}
if (nret != NULL) {
*nret = old_head->n;
}
new_head = old_head->next;
free(old_head);
if (new_head == NULL) {
*endp = NULL;
}
*headp = new_head;
return 1;
}
void print_list(NODE *start)
{
NodeQueue *head = NULL;
NodeQueue *end = NULL;
NODE *current;
current = start;
/* Iterate all `pNext` nodes, then pop each `pDown` node and repeat. */
for (;;) {
/* Add the "down" node to the node queue. */
if (current->pDown != NULL) {
if (!enqueue(&head, &end, current->pDown)) {
perror("warning: could not add node to queue");
}
}
printf("%s", current->pszNode);
/*
* Move to the "next" node.
* If there is no next node, get the first "down" node from the queue.
* If there is no "down" node, break the loop to end processing.
*/
current = current->pNext;
if (current == NULL) {
if (!dequeue(&head, &end, &current)) {
break;
}
}
}
}
This will iterate through all pNext items before moving to a pDown item. The following 2-D list will be printed as A B C D E F G H I J K L M N O P Q:
A
|
B--C
|
D--E-----------F
| |
G-----H I-----J
| | | |
K--L M--N O P
|
Q
You can reverse the priority of pDown/pNext in the print_list function by swapping pNext and pDown inside it, so pNext items are added to the queue and pDown items are iterated until exhausted, which will change the order in which the items are printed to A B D C E G K F I O H M Q L J P N unless you change the structure of the list.
You can see an example using both the code above and the first sample 2-D linked list above at https://repl.it/NjyV/1, though I changed the definition of NODE to make the code using its fields a bit simpler.

How to use unknow data types in C

Below is my code that provides a simple interface to link lists in C. So that it can behave simular to ArrayLists in java.
My question is this:
My code will only work for people who want to have a link list of ints and nothing else.
I understand that they can use the int to hold the address of their data type via pointers.
However, I want something more versatile.
Can I use void* instead of the int in the node struct. Then users can provide int, double, char etc...?
Code:
#include <stdio.h>
#include <stdlib.h>
int AL_appened(int val);
struct Tuple AL_find(int val);
int AL_remove(int val);
int AL_setup();
int AL_len();
typedef struct Node Node;
typedef struct Tuple Tuple;
struct Node{
int val;
Node *next;
};
struct Tuple{
int index;
int val;
};
Node *root, *curr;
int AL_appened(int val) {
Node *tmp;
tmp = (Node *)malloc(sizeof (Node));
curr->next = tmp;
tmp->val = val;
curr = tmp;
root->val++;
return 0;
}
struct Tuple AL_find(int val){
if(root->next) {
curr = root->next;
int count = 0;
while (curr->next){
if (curr->val == val){
Tuple r = {count+=1, val};
return r;
}
count++;
curr = curr->next;
}
if (curr->val == val){
Tuple r = {count+=1, val};
return r;
}
}
Tuple r = {-1, -1};
return r;
}
int AL_remove(int val){
Node *prev;
prev = (Node *)malloc(sizeof (Node));
curr = root;
while (curr->next->val != val){
prev = curr;
curr = curr->next;
}
if (curr->next->val != val) return -1;
curr->next = curr->next->next;
root->val--;
free(curr->next);
return 1;
}
int AL_setup(){
root = (Node *)malloc(sizeof(Node));
root->val = 0;
root->next = 0;
curr = root;
return 0;
}
int AL_len(){
return root->val;
}
void printAll(){
curr=root->next;
while (curr->next != NULL) {
printf("%d\n",curr->val);
curr=curr->next;
}
printf("%d\n",curr->val);
}
int main(){
AL_setup(); //setup the root, we will use root to keep track of the number of links
AL_appened(1); // append 1 so it should look like root>1
AL_appened(2); // append 2 so it should look like root>1>2
AL_appened(3);
AL_appened(4);
printf("%d\n", AL_len()); // print len of list
Tuple results = AL_find(4); // find 4 in list
printf("%d %d\n", results.index, results.val); // return the index and the number found
AL_remove(3);
Tuple results2 = AL_find(4);
printf("%d %d\n", results2.index, results2.val);
results2 = AL_find(4);
printf("%d %d\n", results2.index, results2.val);
printAll(); // print entire list
return 0;
}
Well, you could have void* as the value type, but that would require an extra memory allocation per-node. Another approach I've seen is to put only the link in the struct, and have the user declare their own node type (with the link first), and cast to the generic node type. I've even seen linked list libraries put in preprocessor macros, such that DEFINE_LINKED_LIST(Foo) makes a FooList, a FooNode, an appendFoo function, etc. Finally, you could put all the types you think you might want into a union for the value.
Ultimately, there's no especially clean, pretty way of doing this; C is not well-suited to polymorphism. You'll need to decide which imperfect option you like best.
The linux programmers had a similar problem, and they came up with a general solution to it. In short, their approach is to define a list_head structure, that is inserted into whatever user structure that needs to be part of a linked list. Since the inclusion is the other way around as in your code, the linked list implementation 1. does not constrict the user structure in any way, and 2. allows a user structure to be a member of more than one linked lists. This is really a very flexible design, and as it's GPL'd, you can use it in any GPL'd code.
(This answer to another question on SO points to a user space adaption of the kernel lists. I have not tested it myself, so use it at your own risk. It looks sane, though.)

Add an element to a single linked list

typedef struct list
{
struct list * next;
int val;
}*list_t;
list_t add(list_t l,int e)
{
list_t head;
if(l == NULL)
{
l = malloc(sizeof(list_t));
l->val = e;
l->next = NULL;
return l;
}
head = l;
while(l != NULL)
l=l->next;
l = malloc(sizeof(list_t));
l->val = e;
l->next = NULL;
return head;
}
Sample driver:
int main()
{
list_t ints=NULL;
int i;
for(i=0;i<156;i+=2)
ints = add(ints,i);
while(ints->next != NULL)
{
printf("%d\n",ints->val);
ints=ints->next;
}
system("pause");
return 0;
}
Program works, but "add" function rewinds the list so that the body of main's loop is never achieved.It surprised me a lot, because I thought that I'd been passing list as a value! Could you explain this phenomenom?
The problem is not that the add function rewinds the list, is that it's not working at all: Nowhere in your code are you stating that the previous end of the list should link to the newly added element.
I've modified it slightly:
typedef struct list
{
struct list * next;
int val;
} list_t;
list_t *add(list_t *l,int e)
{
list_t *head;
if(l == NULL)
{
l = malloc(sizeof(list_t));
l->val = e;
l->next = NULL;
return l;
}
head = l;
while(l->next != NULL)
l=l->next;
l->next = malloc(sizeof(list_t));
l=l->next;
l->val = e;
l->next = NULL;
return head;
}
int main()
{
list_t *ints=NULL;
int i;
for(i=0;i<156;i+=2)
ints = add(ints,i);
while(ints->next != NULL)
{
printf("%d\n",ints->val);
ints=ints->next;
}
return 0;
}
The code now works as expected.
Remember that l is a local variable in the add function. Any changes made to l will be lost if it's not allowed to leave the scope of the function somehow (like you do when you return it, inside the first if). Changes made to the variable l points to, using either the * or the -> operators, will be effective to whoever has access to that variable.
I recomend that you start reading on debugging techniques. They vary depending on your environment, and can go from cryptic commandline tools like gdb to full-fledged graphical object browsers and such. This way you will be able to see what happens step by step and monitor memory changes and check what's really being stored in your variables.
EDIT: Fixed pointer trouble as commented. Memory allocations now provide for the whole struct variable, and pointers are no longer used implicitly.
Avoid the special cases. The add() function can do only one thing: allocate a list node and assign its pointer value to the first node in the chain that happens to be null. There is no difference between a NULL node at the head of the chain, in the middle, or at the tail. (of course null nodes cannot exist in the middle of the list. They can exist at the head of the list, but then the list would be empty) Find the first NULL and put the fresh node there.
struct list *add(struct list *lp, int e)
{
struct list **pp;
for (pp= &lp; *pp; pp = &(*pp)->next) {;}
*pp = malloc(sizeof **pp);
(*pp)->val = e;
(*pp)->next = NULL;
return lp;
}
l = malloc(sizeof(list_t));
that allocate a pointer to the struct, not the struct itself.
for example, on a 64 bit machine, the malloced size is 8, but it's supposed to be 16.
when you subsequently say
l->val = ..
l->next = ..
only God knows where you are writing to..
Go search some sample code of linked list, and read it through, I mean in the debugger.

How to implement a linked list in C?

I am creating a linked list as in the previous question I asked. I have found that the best way to develop the linked list is to have the head and tail in another structure. My products struct will be nested inside this structure. And I should be passing the list to the function for adding and deleting. I find this concept confusing.
I have implemented the initialize, add, and clean_up. However, I am not sure that I have done that correctly.
When I add a product to the list I declare some memory using calloc. But I am thinking shouldn't I be declaring the memory for the product instead. I am really confused about this adding.
Many thanks for any suggestions,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRODUCT_NAME_LEN 128
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
struct product_data_t *next;
}product_data_t;
typedef struct list
{
product_data_t *head;
product_data_t *tail;
}list_t;
void add(list_t *list, int code, char name[], int cost);
void initialize(list_t *list);
void clean_up(list_t *list);
int main(void)
{
list_t *list = NULL;
initialize(list);
add(list, 10, "Dell Inspiron", 1500);
clean_up(list);
getchar();
return 0;
}
void add(list_t *list, int code, char name[], int cost)
{
// Allocate memory for the new product
list = calloc(1, sizeof(list_t));
if(!list)
{
fprintf(stderr, "Cannot allocated memory");
exit(1);
}
if(list)
{
// First item to add to the list
list->head->product_code = code;
list->head->product_cost = cost;
strncpy(list->head->product_name, name, sizeof(list->head->product_name));
// Terminate the string
list->head->product_name[127] = '/0';
}
}
// Initialize linked list
void initialize(list_t *list)
{
// Set list node to null
list = NULL;
list = NULL;
}
// Release all resources
void clean_up(list_t *list)
{
list_t *temp = NULL;
while(list)
{
temp = list->head;
list->head = list->head->next;
free(temp);
}
list = NULL;
list = NULL;
temp = NULL;
}
============================== Edited ============================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define PRODUCT_NAME_LEN 64
// typedef struct product_data product_data_t;
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
}product_data_t;
typedef struct list
{
struct list *head;
struct list *tail;
struct list *next;
struct list *current_node;
product_data_t *data;
}list_t;
void add(list_t *list, int code, char name[], int cost);
int main(void)
{
list_t *list = NULL;
list = initialize(list);
add(list, 1001, "Dell Inspiron 2.66", 1299);
add(list, 1002, "Macbook Pro 2.66", 1499);
clean_up(list);
getchar();
return 0;
}
void add(list_t *list, int code, char name[], int cost)
{
/* Allocate memory for the new product */
product_data_t *product = (product_data_t*) calloc(1, sizeof(*product));
if(!product)
{
fprintf(stderr, "Cannot allocate memory.");
exit(1);
}
/* This is the first item in the list */
product->product_code = code;
product->product_cost = cost;
strncpy(product->product_name, name, sizeof(product->product_name));
product->product_name[PRODUCT_NAME_LEN - 1] = '\0';
if(!list->head)
{
/* Assign the address of the product. */
list = (list_t*) product;
/* Set the head and tail to this product */
list->head = (list_t*) product;
list->tail = (list_t*) product;
}
else
{
/* Append to the tail of the list. */
list->tail->next = (list_t*) product;
list->tail = (list_t*) product;
}
/* Assign the address of the product to the data on the list. */
list->data = (list_t*) product;
}
If you are looking to better understand the basics of linked lists, take a look at the following document:
http://cslibrary.stanford.edu/103/LinkedListBasics.pdf
Arguably you want your list data structure to be external to the data that it stores.
Say you have:
struct Whatever
{
int x_;
}
Then your list structure would look like this:
struct Whatever_Node
{
Whatever_Node* next_
Whatever* data_
}
Ryan Oberoi commented similarly, but w/o example.
In your case the head and tail could simply point to the beginning and end of a linked-list. With a singly linked-list, only the head is really needed. At it's most basic, a linked-list can be made by using just a struct like:
typedef struct listnode
{
//some data
struct listnode *next;
}listnodeT;
listnodeT *list;
listnodeT *current_node;
list = (listnodeT*)malloc(sizeof(listnodeT));
current_node = list;
and as long as list is always pointing to the beginning of the list and the last item has next set to NULL, you're fine and can use current_node to traverse the list. But sometimes to make traversing the list easier and to store any other data about the list, a head and tail token are used, and wrapped into their own structure, like you have done. So then your add and initialize functions would be something like (minus error detection)
// Initialize linked list
void initialize(list_t *list)
{
list->head = NULL;
list->tail = NULL;
}
void add(list_t *list, int code, char name[], int cost)
{
// set up the new node
product_data_t *node = (product_data_t*)malloc(sizeof(product_data_t));
node->code = code;
node->cost = cost;
strncpy(node->product_name, name, sizeof(node->product_name));
node->next = NULL;
if(list->head == NULL){ // if this is the first node, gotta point head to it
list->head = node;
list->tail = node; // for the first node, head and tail point to the same node
}else{
tail->next = node; // append the node
tail = node; // point the tail at the end
}
}
In this case, since it's a singly linked-list, the tail is only really useful for appending items to the list. To insert an item, you'll have to traverse the list starting at the head. Where the tail really comes in handy is with a doubly-linked list, it allows you to traverse the list starting at either end. You can traverse this list like
// return a pointer to element with product code
product_data_t* seek(list_t *list, int code){
product_data_t* iter = list->head;
while(iter != NULL)
if(iter->code == code)
return iter;
iter = iter->next;
}
return NULL; // element with code doesn't exist
}
Often times, the head and tail are fully constructed nodes themselves used as a sentinel to denote the beginning and end of a list. They don't store data themselves (well rather, their data represent a sentinel token), they are just place holders for the front and back. This can make it easier to code some algorithms dealing with linked lists at the expense of having to have two extra elements. Overall, linked lists are flexible data structures with several ways to implement them.
oh yeah, and nik is right, playing with linked-lists are a great way to get good with pointers and indirection. And they are also a great way to practice recursion too! After you have gotten good with linked-list, try building a tree next and use recursion to walk the tree.
I am not writing the code here but you need to do the following:
Create and object of list, this will remain global for the length of program.
Malloc the size of product _ data _ t.
For first element (head is NULL), point head to the malloced' address.
To add next element, move to the end of list and then add the pointer of malloced address to next of last element. (The next of the last element will always be NULL, so thats how you traverse to end.)
Forget tail for a while.
If you are learning C pointer theory this is a good exercise.
Otherwise, it feels like too much indirection for code that is not generic (as in a library).
Instead of allocating a static 128 byte character string, you might want to do some more pointer practice and use an allocated exact length string that you clean up at exit.
Academically, kungfucraigs' structure looks more generic then the one you have defined.
You're calloc'ing space for your list_t struct, just pointers to list head and tail, which isn't what you want to do.
When you add to a linked list, allocate space for an actual node in the list, which is your product_data_t struct.
You're allocating the wrong chunk of memory. Instead of allocating memory for each list element, you're allocating for the list head and tail.
For simplicity, get rid of the separate structure for the head and tail. Make them global variables (the same scope they're in now) and change them to be listhead and listtail. This will make the code much more readable (you won't be needlessly going through a separate structure) and you won't make the mistake of allocating for the wrong struct.
You don't need a tail pointer unless you're going to make a doubly linked list. Its not a major element to add once you create a linked list, but not necessary either.
In memory your items are linked by pointers in the list structure
item1 -> item2
Why not make the list structure part of your item?
Then you allocate a product item, and the list structure is within it.
typedef struct product_data
{
int product_code;
char product_name[PRODUCT_NAME_LEN];
int product_cost;
struct list_t list; // contains the pointers to other product data in the list
}product_data_t;
I think u first need to Imagin back-end. Code are nothing to important. Go here and visualize back-end basic c code of all insertion.
1) Insertion at beginning Visit and scroll to get every instruction execution on back- end
And u need front and imagin Go here
Back end imagin
And All other possible insertion here.
And important thing u can use this way.
struct Node{
int data;//data field
struct Node*next;//pointer field
};
struct Node*head,*tail; // try this way
or short cut
struct Node{
int data;//data field
struct Node*next;//pointer field
}*head,*tail; //global root pointer
And << Click >> To visualize other linked list problem.
Thanks.
A demo for Singly Linked List. If you prefer, try to check Circular Linked List and Doubly Linked List.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node * next;
} node_t;
// Iterating over a list
void
print_list(node_t *head)
{
node_t *current = head;
while(current != NULL)
{
printf("%d\n", current->val);
current = current->next;
}
}
// Adding an item to the end of the list
void
push_end(node_t *head, int val)
{
node_t *current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = malloc(sizeof(node_t));
current->next->val = val;
current->next->next = NULL;
}
// Adding an item to the head of the list
void
push_head(node_t **head, int val)
{
node_t *new_node = NULL;
new_node = malloc(sizeof(node_t));
new_node->val = val;
new_node->next = *head;
*head = new_node;
}
// Removing the head item of the list
int
pop_head(node_t **head)
{
int retval = -1;
node_t *next_node = NULL;
if (*head == NULL) {
return -1;
}
next_node = (*head)->next;
retval = (*head)->val;
free(*head);
*head = next_node;
return retval;
}
// Removing the last item of the list
int
pop_last(node_t *head)
{
int retval = 0;
node_t *current = NULL;
if (head->next == NULL) {
retval = head->val;
free(head);
return retval;
}
/* get to the second to last node in the list */
current = head;
while (current->next->next != NULL) {
current = current->next;
}
/* now current points to the second to last item of the list.
so let's remove current->next */
retval = current->next->val;
free(current->next);
current->next = NULL;
return retval;
}
// Removing a specific item
int
remove_by_index(node_t **head, int n)
{
int i = 0;
int retval = -1;
node_t *current = *head;
node_t *temp_node = NULL;
if (n == 0) {
return pop_head(head);
}
for (i = 0; i < n - 1; i++) {
if (current->next == NULL) {
return -1;
}
current = current->next;
}
temp_node = current->next;
retval = temp_node->val;
current->next = temp_node->next;
free(temp_node);
return retval;
}
int
main(int argc, const char *argv[])
{
int i;
node_t * testnode;
for (i = 0; i < argc; i++)
{
push_head(&testnode, atoi(argv[i]));
}
print_list(testnode);
return 0;
}
// http://www.learn-c.org/en/Linked_lists
// https://www.geeksforgeeks.org/data-structures/linked-list/
The linked list implementation inspired by the implementation used in the Linux kernel:
// for 'offsetof', see: https://stackoverflow.com/q/6433339/5447906.
#include <stddef.h>
// See: https://stackoverflow.com/q/10269685/5447906.
#define CONTAINER_OF(ptr, type, member) \
( (type *) ((char *)(ptr) - offsetof(type, member)) )
// The macro can't be used for list head.
#define LIST_DATA(ptr, type, member) \
CONTAINER_OF(ptr, type, member);
// The struct is used for both: list head and list nodes.
typedef struct list_node
{
struct list_node *prev, *next;
}
list_node;
// List heads must be initialized by this function.
// Using the function for list nodes is not required.
static inline void list_head_init(list_node *node)
{
node->prev = node->next = node;
}
// The helper function, mustn't be used directly.
static inline void list_add_helper(list_node *prev, list_node *next, list_node *nnew)
{
next->prev = nnew;
nnew->next = next;
nnew->prev = prev;
prev->next = nnew;
}
// 'node' must be a list head or a part of a list.
// 'nnew' must not be a list head or a part of a list. It may
// be uninitialized or contain any data (even garbage).
static inline void list_add_after(list_node *node, list_node *nnew)
{
list_add_helper(node, node->next, nnew);
}
// 'node' must be a list head or a part of a list.
// 'nnew' must not be a list head or a part of a list. It may
// be uninitialized or contain any data (even garbage).
static inline void list_add_before(list_node *node, list_node *nnew)
{
list_add_helper(node->prev, node, nnew);
}
// 'node' must be part of a list.
static inline list_node *list_del(list_node *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
return node->prev;
}
Example of usage:
#include <stdio.h>
// The struct must contain 'list_node' to be able to be inserted to a list
typedef struct
{
int data;
list_node node;
}
my_struct;
// Convert 'list_node *' to 'my_struct*' that contains this 'list_node'
static inline my_struct* get_my_struct(list_node *node_ptr)
{
return LIST_DATA(node_ptr, my_struct, node);
}
void print_my_list(list_node *head)
{
printf("list: {");
for (list_node *cur = head->next; cur != head; cur = cur->next)
{
my_struct *my = get_my_struct(cur);
printf(" %d", my->data);
}
printf(" }\n");
}
// Print 'cmd' and run it. Note: newline is not printed.
#define TRACE(cmd) \
(printf("%s -> ", #cmd), (cmd))
int main()
{
// The head of the list and the list itself. It doesn't contain any data.
list_node head;
list_head_init(&head);
// The list's nodes, contain 'int' data in 'data' member of 'my_struct'
my_struct el1 = {1};
my_struct el2 = {2};
my_struct el3 = {3};
print_my_list(&head); // print initial state of the list (that is an empty list)
// Run commands and print their result.
TRACE( list_add_after (&head , &el1.node) ); print_my_list(&head);
TRACE( list_add_after (&head , &el2.node) ); print_my_list(&head);
TRACE( list_add_before(&el1.node, &el3.node) ); print_my_list(&head);
TRACE( list_del (head.prev) ); print_my_list(&head);
TRACE( list_add_before(&head , &el1.node) ); print_my_list(&head);
TRACE( list_del (&el3.node) ); print_my_list(&head);
return 0;
}
The result of execution of the code above:
list: { }
list_add_after (&head , &el1.node) -> list: { 1 }
list_add_after (&head , &el2.node) -> list: { 2 1 }
list_add_before(&el1.node, &el3.node) -> list: { 2 3 1 }
list_del (head.prev) -> list: { 2 3 }
list_add_before(&head , &el1.node) -> list: { 2 3 1 }
list_del (&el3.node) -> list: { 2 1 }
http://coliru.stacked-crooked.com/a/6e852a996fb42dc2
Of course in real life you will most probably use malloc for list elements.
In C language, we need to define a Node to store an integer data and a pointer to the next value.
struct Node{
int data;
struct Node *next;
};
To add a new node, we have a function add which has data as an int parameter. At first we create a new Node n. If the program does not create n then we print an error message and return with value -1. If we create the n then we set the data of n to have the data of the parameter and the next will contain the root as it has the top of the stack. After that, we set the root to reference the new node n.
#include <stdio.h>
struct node
{
int data;
struct node* next;
};
int main()
{
//create pointer node for every new element
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
//initialize every new pointer with same structure memory
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 18;
head->next = second;
second->data = 20;
second->next = third;
third->data = 31;
third->next = NULL;
//print the linked list just increment by address
for (int i = 0; i < 3; ++i)
{
printf("%d\n",head->data++);
return 0;
}
}
This is a simple way to understand how does pointer work with the pointer. Here you need to just create pointer increment with new node so we can make it as an automatic.
Go STL route. Declaring linked lists should be agnostic of the data. If you really have to write it yourself, take a look at how it is implemented in STL or Boost.
You shouldn't even keep the *next pointer with your data structure. This allows you to use your product data structure in a various number of data structures - trees, arrays and queues.
Hope this info helps in your design decision.
Edit:
Since the post is tagged C, you have equivalent implementations using void* pointers that follow the basic design principle. For an example, check out:
Documentation | list.c | list.h

Resources