Generic LinkedLists in C - c

I am quite new to C and having a lot of trouble with generic linked lists in c.
Im trying to convert my linked list into a generic one but I don't really understand how to.
This is my original one:
typedef struct LLNode {
int rowPos;
int colPos
char Charecter
struct LLNode *next;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
} LinkedList;
I understand that the data has to be a void but can you have more than one void *data; in a node.
So far I have this:
typedef struct LLNode {
void *data;
struct LLNode *next;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
} LinkedList;
But I don't know how I go about accessing and changing 3 lots of data in one void *data.

You can use macros:
#define LNODE(Type) LNode_ ## Type
#define LLIST(Type) LList_ ## Type
#define DECL_LINKED_LIST(Type) \
typedef struct LNODE(Type) { Type value; struct LNODE(Type)* next; } LNODE(Type); \
typedef struct LLIST(Type) { LNODE(Type)* head; LNODE(Type)* tail; } LLIST(Type);
typedef struct {
char const* f_name;
char const* l_name;
} Person;
DECL_LINKED_LIST(Person);
int main() {
LLIST(Person) list;
LNODE(Person) node1;
list.head = list.tail = &node1;
node1.next = 0;
node1.value.f_name = "John";
node1.value.l_name = "Smith";
}
It's somewhat ugly, but it works. Alternatively, if you can use a C++ compiler instead, you can use templates.

C does not have typed generic aggregates such as C++ templates, but you can implement simpler aggregates pointing to data items via void * pointers. You can also use macros to mix the data and the aggregation internals, but it requires more advanced C skills.
Here is an example using void * for data:
#include <stdio.h>
#include <stdlib.h>
/* generic list handling */
typedef struct LLNode {
struct LLNode *next;
void *data;
} LLNode;
typedef struct LinkedList {
LLNode *head;
LLNode *tail;
} LinkedList[1];
void LinkedList_init(LinkedList list) {
if (list) {
list->head = list->tail = NULL;
}
}
void *LinkedList_append(LinkedList list, void *data) {
if (list) {
LLNode *node = malloc(sizeof(*node));
if (node != NULL) {
node->data = data;
node->next = NULL;
if (list->head == NULL) {
list->head = list->tail = node;
} else {
list->tail = list->tail->next = node;
}
return data;
}
}
return NULL;
}
void *LinkedList_delete(LinkedList list, void *data) {
if (list) {
for (LLNode **np = &list->head, *last = NULL; *np;) {
LLNode *node = *np;
if (node->data == data) {
if ((*np = node->next) == NULL)
list->tail = last;
free(node);
return data;
} else {
last = node;
np = &node->next;
}
}
}
return NULL;
}
void LinkedList_free(LinkedList list, int free_data) {
if (list) {
for (LLNode *node = list->head, *next; node; node = next) {
next = node->next;
if (free_data)
free(node->data);
free(node);
}
list->head = list->tail = NULL;
}
}
#define LinkedList_foreach(var, list) \
for (LLNode *np__ = (list)->head, *next__; np__ != NULL; np__ = next__) \
for (var = (next__ = np__->next, np__)->data; np__; np__ = NULL)
/* use a generic list for my data */
typedef struct MyData {
int rowPos;
int colPos;
char Character;
} MyData;
typedef struct MyList {
int ROW;
int COL;
int appleCount;
int winCon;
int snakeSize;
LinkedList list; // linked list of MyData items
} MyList;
MyList *MyList_alloc(void) {
MyList *lp = calloc(sizeof(*lp), 1);
LinkedList_init(lp->list);
return lp;
}
void MyList_free(MyList *lp) {
LinkedList_free(lp->list, 1);
free(lp);
}
MyData *MyList_add(MyList *lp, int row, int col, char c) {
MyData *dp = malloc(sizeof(*dp));
dp->rowPos = row;
dp->colPos = col;
dp->Character = c;
return LinkedList_append(lp->list, dp);
}
void MyList_delete(MyList *lp, MyData *dp) {
free(LinkedList_delete(lp->list, dp));
}
void MyList_print(MyList *lp) {
printf("{\n");
LinkedList_foreach(MyData *dp, lp->list) {
printf(" { %d, %d, '%c' }\n", dp->rowPos, dp->colPos, dp->Character);
}
printf("};\n");
}
void MyList_filter_diagonal(MyList *lp) {
LinkedList_foreach(MyData *dp, lp->list) {
if (dp->rowPos == dp->colPos)
MyList_delete(lp, dp);
}
}
int main() {
MyList *mylist = MyList_alloc();
MyList_add(mylist, 0, 0, 'A');
MyData *d1 = MyList_add(mylist, 1, 2, 'B');
MyList_add(mylist, 2, 2, 'C');
MyList_add(mylist, 3, 5, 'D');
MyList_print(mylist);
MyList_delete(mylist, d1);
MyList_print(mylist);
MyList_filter_diagonal(mylist);
MyList_print(mylist);
MyList_free(mylist);
return 0;
}

Related

I am trying to reverse a linked list using recursion in C, I have some doubts on my recursive function

Below is the program
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
struct node* reverse_ll(struct node* hnode)
{
if(hnode == 0)
{
return 0;
}
if(hnode->next == 0)
{
head=hnode;
return hnode;
}
struct node* ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next=0;
//return hnode;
}
void display()
{
struct node *ptr;
ptr=head;
if(ptr==0)
{
printf("empty");
}
else
{
while(ptr!=0)
{
printf("%d->",ptr->data);
ptr=ptr->next;
}
printf("null");
}
}
int main()
{
struct node* h;
lastinsert(1);
lastinsert(2);
lastinsert(3);
lastinsert(4);
lastinsert(5);
display();
h=reverse_ll(head);
display();
return 0;
}
In function reverse_ll() even if I comment "return hnode" I am getting the right output How is it possible where does ptr receives its address from when I comment "return hnode"?
output: 1->2->3->4->5->null
5->4->3->2->1->null
reverse_ll() must return a struct node * in the recursive case:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head;
void lastinsert(int data) {
struct node **c = &head;
for(; *c; c = &(*c)->next);
*c = malloc(sizeof(*head));
if (!(*c)) {
printf("malloc failed\n");
return;
}
(*c)->data = data;
(*c)->next = NULL;
}
struct node *reverse_ll(struct node* hnode) {
if(!hnode)
return NULL;
if(!hnode->next) {
head = hnode;
return hnode;
}
struct node *ptr=reverse_ll(hnode->next);
ptr->next=hnode;
hnode->next = NULL;
return hnode;
}
void display() {
if(!head) {
printf("empty");
return;
}
for(struct node *ptr = head; ptr; ptr = ptr->next) {
printf("%d->",ptr->data);
}
printf("null\n");
}
int main() {
for(int i = 1; i <= 5; i++) {
lastinsert(i);
}
display();
reverse_ll(head);
display();
// It's good practice to implement a function that frees you list
// which you would call here.
return 0;
}
and example run:
$ ./a.out
1->2->3->4->5->null
5->4->3->2->1->null

Defining list and inner dictionary as the value of a dictionary in c

I am very new in c language and I am so sorry if my question is too basic.
I want to define a dictionary in c in which I have a list as the value of my keys. In other word, I like to have something like this is python in c:
my_dictionary = {1:{'name':'john','items':['item1','item2']},2:{'name':'bob','items':['item3','item4']}}
Then I like to have access to my defined dictionary as this:
my_item = my_dictionary[1]['items'].
I know this is very easy in python but for c, I could not find a good example for this. I am able to define simple dictionaries such as:
typedef struct dict_t_struct {
char *key;
void *value;
struct dict_t_struct *next;
} dict_t;
and I can easily add, remove, or print items from this dictionary using below functions:
dict_t **dictAlloc(void) {
return malloc(sizeof(dict_t));
}
void dictDealloc(dict_t **dict) {
free(dict);
}
void *getItem(dict_t *dict, char *key) {
dict_t *ptr;
for (ptr = dict; ptr != NULL; ptr = ptr->next) {
if (strcmp(ptr->key, key) == 0) {
return ptr->value;
}
}
return NULL;
}
void delItem(dict_t **dict, char *key) {
dict_t *ptr, *prev;
for (ptr = *dict, prev = NULL; ptr != NULL; prev = ptr, ptr = ptr->next) {
if (strcmp(ptr->key, key) == 0) {
if (ptr->next != NULL) {
if (prev == NULL) {
*dict = ptr->next;
} else {
prev->next = ptr->next;
}
} else if (prev != NULL) {
prev->next = NULL;
} else {
*dict = NULL;
}
free(ptr->key);
free(ptr);
return;
}
}
but the problem is that I need to have linked list as the values of my dictionary and an inner dictionary in my dictionary.
1 Your structure is json, you can't use the normal dictionary completely
2 If you need to store a list, you need to define the data structure of the list.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DICT_STRING 1
#define DICT_LIST 2
typedef struct list_node {
void* value;
struct list_node* next;
} list_node;
typedef struct list {
list_node* head;
} list;
typedef struct dict_entry {
int type;
char* key;
void* value;
struct dict_entry* next;
} dict_entry;
typedef struct dict_t {
dict_entry* head;
} dict_t;
dict_t* dictAlloc(void) {
dict_t* d = malloc(sizeof(dict_t));
d->head = NULL;
return d;
}
void dictDealloc(dict_t* dict) {
free(dict);
}
dict_entry* addItem(dict_t* dict, int type, char* key, void* value) {
dict_entry* de = malloc(sizeof(*de));
de->type = type;
de->key = key;
de->value = value;
de->next = dict->head;
dict->head = de;
return de;
}
dict_entry* getItem(dict_t* dict, char* key) {
dict_entry* de = dict->head;
while (de) {
if (strcmp(de->key, key) == 0) {
return de;
}
de = de->next;
}
return NULL;
}
int main(int argc, char** argv) {
dict_t* d = dictAlloc();
dict_entry* de;
list* l = malloc(sizeof(*l));
list_node* n = malloc(sizeof(*n));
n->value = "value";
l->head = n;
addItem(d, DICT_LIST, "key", l);
de = getItem(d, "key");
switch (de->type) {
case DICT_LIST: {
list* l = de->value;
printf("%s", l->head->value);
}
}
}

how to make a struct with void * data?

i have this struct :
struct node
{
int data;
struct node *next;
};
so the following strcut has an int data , i want the function to accept CopyFunction which is baisicly a pointer to a function that accepts void* and returns void* , i want my function to get a copy of the data in the first node connected to a copy f the second data , now i want the data to be not only int i want to use this function on any data so i used CopyFunction to be pointer to a function that as i saied accepts void* ... how can i use this in the function bellow .. for example if i want to change the struct to be :
struct node
{
Element data;
struct node *next;
};
typedef void* Element;
typedef Element (*copy_function) (Element);
struct node * concatLists( struct node *head1, struct node *head2, int cmp( struct node *),copy_function CopyFunction)
{
struct node *head = NULL;
struct node **current = &head;
for ( ; head1 != NULL; head1 = head1->next )
{
if ( cmp( head1 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = CopyFunction(head1->data);
( *current )->next = NULL;
current = &( *current )->next;
}
}
for ( ; head2 != NULL; head2 = head2->next )
{
if ( cmp( head2 ) )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = CopyFunction(head2->data);
( *current )->next = NULL;
current = &( *current )->next;
}
}
and then if i have a int struct i can just use this function with a copy function for int like this :
static void* copyInt(void* num){
int* newInt=malloc(sizeof(*newInt));
*newInt=*(int*)num;
return newInt;
}
also i think it is better if i change and without using always struct node * i want to have maybe: typedef struct node_t* Node;
concatLists(..., (copy_function)copyInt)
Providing all the "methods" (cmp and CopyFunction) as parameters gets silly fast. Why not create a List "object" that holds not just a pointer to the head and tail, but the "methods" to genericize the list too.
cmp is probably a compare function (which means it should take two arguments), which means you are probably trying to merge sorted lists. Well, here's code that uses a generic list implementation to do just that. (I figured I might as well make malloc and free plugable as well.)
#include <stdio.h>
#include <stdlib.h>
// -----
// ListNode type declarations.
typedef struct ListNode {
void* data;
struct ListNode* prev;
struct ListNode* next;
} ListNode;
// -----
// ListType type declarations.
typedef void* (* Allocator )(size_t);
typedef void (* Deallocator )(void*);
typedef void (* FreeFunction )(void*);
typedef int (* CmpFunction )(void*, void*);
typedef void* (* CopyFunction )(void*);
typedef struct {
Allocator malloc;
Deallocator free;
FreeFunction free_data;
CmpFunction cmp;
CopyFunction copy;
} ListType;
// -----
// List type declarations.
typedef struct {
const ListType* list_type;
ListNode* head;
ListNode* tail;
} List;
typedef void (*ListVisitor)(void*);
// -----
// ListDataInt definitions.
static void* ListDataInt_new(int i) {
int* ip = malloc(sizeof(int));
*ip = i;
return ip;
}
static void ListDataInt_free_data(int* ip) {
free(ip);
}
static int ListDataInt_cmp(const int* ap, const int* bp) {
if (*ap < *bp) return -1;
if (*ap > *bp) return +1;
return 0;
}
static int* ListDataInt_copy(const int* orig_ptr) {
int* new_ptr = malloc(sizeof(int));
*new_ptr = *orig_ptr;
return new_ptr;
}
static const ListType ListDataInt_list_type = {
malloc,
free,
(FreeFunction)ListDataInt_free_data,
(CmpFunction)ListDataInt_cmp,
(CopyFunction)ListDataInt_copy
};
// -----
// ListNode definitions.
static ListNode* ListNode_new(List* list, void* data) {
const ListType* list_type = list->list_type;
ListNode* node = list_type->malloc(sizeof(ListNode));
node->data = data;
node->prev = NULL;
node->next = NULL;
return node;
}
static void ListNode_free(List* list, ListNode* node) {
const ListType* list_type = list->list_type;
list_type->free_data(node->data);
list_type->free(node);
}
// -----
// List definitions.
static List* List_new(const ListType* list_type) {
List* list = list_type->malloc(sizeof(List));
list->list_type = list_type;
list->head = NULL;
list->tail = NULL;
return list;
}
static void List_free(List* list) {
ListNode* next = list->head;
while (next != NULL) {
ListNode* node = next;
next = node->next;
ListNode_free(list, node);
}
list->list_type->free(list);
}
static void List_push(List* list, ListNode* node) {
if (list->tail == NULL) {
list->head = list->tail = node;
} else {
list->tail->next = node;
node->prev = list->tail;
list->tail = node;
}
}
static void List_push_data(List* list, void* data) {
List_push(list, ListNode_new(list, data));
}
static void List_visit(List* list, ListVisitor visitor) {
for (ListNode* node = list->head; node != NULL; node = node->next) {
visitor(node->data);
}
}
// -----
// Main program.
static List* merge_sorted_lists(List* list1, List* list2) {
const ListType* list_type = list1->list_type;
List* new_list = List_new(list_type);
ListNode* src1 = list1->head;
ListNode* src2 = list2->head;
while (src1 != NULL && src2 != NULL) {
int cmp = list_type->cmp(src1->data, src2->data);
if (cmp <= 0) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
src1 = src1->next;
}
if (cmp >= 0) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
src2 = src2->next;
}
}
while (src1 != NULL) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src1->data)));
src1 = src1->next;
}
while (src2 != NULL) {
List_push(new_list, ListNode_new(new_list, list_type->copy(src2->data)));
src2 = src2->next;
}
return new_list;
}
static void dumper(const int* ip) {
printf("%d\n", *ip);
}
int main(void) {
List* sorted_int_list1 = List_new(&ListDataInt_list_type);
List_push_data(sorted_int_list1, ListDataInt_new(4));
List_push_data(sorted_int_list1, ListDataInt_new(6));
List_push_data(sorted_int_list1, ListDataInt_new(8));
List* sorted_int_list2 = List_new(&ListDataInt_list_type);
List_push_data(sorted_int_list2, ListDataInt_new(5));
List_push_data(sorted_int_list2, ListDataInt_new(7));
List_push_data(sorted_int_list2, ListDataInt_new(9));
List* merged_sorted_int_list =
merge_sorted_lists(sorted_int_list1, sorted_int_list2);
List_visit(merged_sorted_int_list, (ListVisitor)dumper);
List_free(sorted_int_list1);
List_free(sorted_int_list2);
List_free(merged_sorted_int_list);
return 0;
}
Test:
$ gcc -Wall -Wextra -pedantic --std=c99 -o a a.c && a
4
5
6
7
8
9

My LinkedList structure isn't functioning in C

I've been struggling with this for a while, I can't seem to create a valid LinkedList data structure in C,
Here's all my structures:
typedef struct {
int size;
int *cellsI;
int *cellsJ;
} DataInList;
typedef struct listElement{
DataInList dataVar;
struct listElement *next;
} LinkedListElement;
typedef struct {
LinkedListElement*first;
LinkedListElement*last;
} LinkedListRoot;
I have a function that adds a data element to the linked list:
public void addDataToList(LinkedListRoot root, DataInList data) {
LinkedListElement newElem;
newElem.dataVar = data;
newElem.next = NULL;
if(root->first == NULL) {
root->first = &newElem;
root->last = &newElem;
} else {
root->last->next = &newElem;
root->last = &newElem;
}
}
Can anyone help me please?
As the commenter said, you've defined newElem in the function, and on the stack as well, so you have no way to globalize it or return a permanent entry to it. Something more along these lines. I haven't tested it yet, but it should give you the idea:
typedef listData struct {
int size;
int *cellsI;
int *cellsJ;
} listData_t
typedef struct listElement {
listData_t dataVar;
struct listElement *next;
} listElement_t;
typedef struct listRoot {
listElement_t *first;
listElement_t *last;
} listRoot_t;
listElement_t *
addDataToList(listRoot_t *root, listData_t *data) {
listElement_t *newElem = malloc(sizeof(struct listElement));
if (newElem == NULL) {
fprintf(stderr, "Error allocating memory\n");
exit(-1)
}
newElem->dataVar = data;
newElem->next = NULL;
if (root->first == NULL) {
root->first = newElem;
root->last = newElem;
} else {
root->last->next = newElem;
root->last = newElem;
}
return newElem;
}

Swap nodes in a double linked list - slow sorting algorithm drops nodes

For practice, I've been working on a compressor which does the find-repeated-parts, make-dictionary, compress-with-huffman codes thing.
It's not really working.
One of the problems is, for some reason my sorting algorithm drops keywords from the dictionary. I think the problem is in the swap routine, but I'm not sure.
( this routine swaps adjacent keywords, with next being current->next ).
I do have a static keyword * head;
void swap(keyword * current, keyword * next) {
keyword * prev = current->prev;
if (prev){
prev->next = next;
next->prev = prev;
} else { /* no prev - current is head */
head = next;
next->prev = 0;
}
current->prev = next;
current->next = next->next;
next->next = current;
}
Spot anything wrong with this?
You don't set next->next->prev.
Getting data-structure implementations correct is notoriously difficult. The way to spot this sort of thing is to work out how many pointers should need updating (6). You're only updating 5, so one must be missing!
I have seen many question related to Linked Lists, so I decide to share my Linked List version, so it can be adapted and/or improved. This version is written in C++, some methods were omitted for saving space:
class Node {
friend class LinkedList;
public:
Node();
Node(const node& krNode);
explicit Node(const int kiData);
virtual ~Node();
Node& operator=(const Node& krNode);
int GetData(void) const {return _idata; }
private: int _iData; Node* _pNetxNode;
}
Node::Node(): _iData(0), _pNextNode(0) {}
Node::Node(const Node& krnode): _iData(krNode._iData), _pNextNode(0) {}
Node::~Node() {}
Node& Node::operator=(const Node& krNode) {_iData = krNode._iData; return *this; }
class LinkedList {
public:
LinkedList();
virtual ~LinkedList();
int GethLenght(void) {return _iSize;}
void Append(Node* pNode);
void Insert(const int kiIndex, node* pNode);
Node* GetItem(const int kiIndex);
int IndexOf(Node* pNode);
void Remove(const int kiInde);
void Swap(constconst int kiIndexA, const int kiIndexB);
void Clear(void);
void Print(void);
protected:
LinkedList(const LinkedList& krLinkedList);
LinkedList& operator=(const LinkedList& krLinkedList);
private:
Node* Detach(const int kiIndex);
Node* _pFirstNode;
Node* _pLastNode;
int _iSize;
}
LinkedList::LinkedList() : _pFirstNode(0), _pLastNode(0), _iSize(0) {}
LinkedList::~LinkedList() { Clear(); }
void LinkedList::Append(Node* pnode) { if(0==_iSize{_pFistrNode = pNode; } else { _pLastNode->_pNextNode = pnode; } _pLastNode = pNode; _iSize++; }
void LinkedList::Insert(const int kiIndex, node* pNode) {
Node* pNext = 0; Node* pPrevious = 0;
if(0==_iSize) { Append(pNode); }
else {
if(0==kiIndex){ pNode->_pNextNode = _pFirstNode; _pFirstNode = pNode; }
else { pPrevious = Getitem(kiIndex-1); pNext=pPrevoius->_pNextnode; pNode->_pNextNode=pNext; pPrevious->_pNextnode=pNode;}
} _iSize++;
}
Node* LinkedList::GetItem(const int kiIndex){
Node* pNode = _pFirstNode; int iCounter = 0;
while(icounter++ != kiIndex) { pNode = pNode->_pNextnode; }
return pNode;
}
int LinkedList::IndexOf(Node* pSearchNode){
node* pNode = _pFirstnode; int iIndex=0;
while(o != pNode) { if(pnode==pSearchNode) { break;} iIdex++; pNode=pnode->_pnextnode; }
if(iIndex ==_iSize) {iIndex = -1;}
return iIndex;
}
void LinkedList::Remove(const int kiIndex){ delete Detach(kiIndex); }
void LinkedList::Swap(const int kiIndexA, const int kiIndexB){
int iLowIndex = 0; int iHighIndex = 0;
if(kiIndex>==kiIndexB) {return;}
iLowIndex = (kiIndexA < kiIndexB) ? kiIndexA : kiIndexB;
iHighIndex = (kiIndexA > kiIndexB) ? kiIndexA : kiIndexB;
Insert(iHighIndex, Detach(iLowIndex));
Insert(iLowIndex, Detach(iHighIndex-1));
}
void LinkedList::Clear(void) {
Node* pNode=_pFirstNode; while(0!=pnode){delete pNode; pNode=pNode-_pNextNode;}
_pFirstnode=0; _pLastnode=0;
}
void LinkedList::Print(void) {
Node* pNode = _pFirstNode;
while(0 != pnode) {printf("%d ", pNode_iData); pNode = pNode->_pNextNode;}
}
Node* LinkedList::Detach(const int kiindex){
Node* pnode = _pFirstnode; Node* pToDetachNode = 0;
if(kiIndex==0){
pToDetachNode = _pFirstNode; _pFirstNode=pnode->_pNextNode; if(1==_iSize){_pLastNode=0;}
}
else{
Node* pPreviousNode = GetItem(kiIndex-1);
pToDetachNode = pPreviousNode->_pNextNode;
if(kiIndex<_iSize){pPreviousNode->_pNextNode=pPreviousNode->_pNextnode; }
else {pPreviousNode->_pNextnode=0; _pLastNode=pPrevoiusNode;}
}_iSize--;
}

Resources