Returning the first node in a list - c

I'm asked to return the first Node in a list, in a given generic struct, but I'm having trouble to figure out the most efficient way to do so.
Is doing a previous pointer (besides next) is the only way?
struct Map_t {
Map next;
MapDataElement currentData;
MapKeyElement currentKey;
};

You provide very little information.
I guess you need something like this:
struct List
{
struct Map_t *head;
struct Map_t *tail;
};
struct Map_t {
struct Map_t *next;
MapDataElement currentData;
MapKeyElement currentKey;
};
// Initialize list for first use
void InitializeList(struct List *l)
{
l->head = l->tail = NULL;
}
// add new data/key pair to list
void AddToList(struct List *l, MapDataElement data, MapKeyElement key)
{
struct Map_t *newnode = malloc(sizeof(*newnode));
newnode->currentData = data;
newnode->currentKey = key;
newnode->next = NULL;
if (l->head == NULL)
{
// special case when list is empty
l->head = l->tail = newnode;
}
else
{
// list is non empty
l->tail->next = newnode; // append new node to tail
l->tail = newnode; // tail becomes newnode
}
}
int main()
{
struct List mylist; // your list
// the head of the list is stored permanently
// in mylist.head
InitializeList(&mylist);
MapDataElement data = ...; // get data from somewhere
MapKeyElement key = ...; // get key from somewhere
AddToList(&mylist, data, key);
...
}
As already stated in a comment: the head of the list is stored permanently mylist.head.
Disclaimer: this is untested and incomplete code. No error checking is done for brevity.

Related

How to init a LinkedList?

I want to init my LinkedList, but failed.
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode* next;
}LNode, *LinkedList;
void Init(LinkedList L)
{
L = (LNode *)malloc(sizeof(LNode));
L->next = NULL;
}
int main()
{
LinkedList head;
Init(head);
return 0;
}
If I Init my LinkedList like this it works.
LNode node = (LNode *)malloc(sizeof(int));
node->data = 5;
node->next = NULL;
LinkedList head = node;
but this will make my head with a value.
void Init(LNode **L, ElemType data)
{
*L = malloc(sizeof(LNode));
(*L)->data = data;
(*L)->next = NULL;
}
int main()
{
LinkedList head;
Init(&head, 0);
// ...
free(head);
return 0;
}
Initializing your head to not contain a value doesn't really make sense, unless you actually want head = NULL which I assume is not the case.
You've chosen to define a linked list as a pointer to an element - the head element.
It's customary to initialize containers (like lists, queues, stacks etc.) to be empty. An empty list has no head element, so the pointer to the head element would be NULL. In other words, you would either write
LinkedList create_list()
{
return NULL;
}
// ...
LinkedList mylist = create_list();
or
void initialize_list(LinkedList* list)
{
*list = NULL;
}
// ...
LinkedList my_list;
initialize_list(&my_list);
The use of malloc() will be in functions which append or prepend a new node to the list.

How to avoid the condition that a variable is auto-allocated to the memory unit that my pointer points to?

I want to insert several nodes into an empty singly-linked list. It's OK when I insert the first node. However, the fist node is replaced by the second node when I call the function
the first time using function ListInsert(), the variable newNode is at the memory unit 0x7fffffffdf50. And the second time calling function ListInsert(), *L = 0x7fffffffdf50, **L = {m_Data = first node data, m_nextNode = NULL}. but when I create the newNode, it is still at the memory unit 0x7fffffffdf50. If I set newNode = second node data, it actually replace the first node but not insert into the linked list
struct t_Node
{
struct t_Data m_Data;
struct t_Node *m_nextNode;
}
typedef struct Node* t_LinkedList;
void ListInsert(t_LinkedList* L, int position, struct t_Data newData)
{
if (!*L)
{
struct t_Node newNode;
newNode.m_Data = newData;
newNode.m_nextNode = NULL;
(*L) = &newNode;
}
/* first Node is not NULL */
else
{
t_LinkedList anIterator;
anIterator = (*L);
if (!(*anIterator).m_nextNode)
{
struct t_Node newNode;
newNode.m_Data = newData;
newNode.m_nextNode = NULL;
(*anIterator).m_nextNode = &newNode;
}
}
}
t_LinkedList aLinkedList;
aLinkedList = NULL;
ListInsert(&aLinkedList,1,data1);
ListInsert(&aLinkedList,2,data2);
I expect to insert the second node based on the singly linked list with one node but not to replace the first node, and to maintain the structure of the program.
When you create new variable inside a function, the memory for that variable is allocated on the stack, that is why when the function returns the memory is no longer accessible. So we need to dynamically allocate memory in the heap. Read this to get a better idea about heap and stack. Here is the modified version of your code using dynamic allocation. Also note that when allocating memory dynamically, we need to free the memory when we are done using it, therefore I added a deleteList() function to delete the list.
#include<stdio.h>
#include<stdlib.h>
struct t_Node
{
int m_Data;
struct t_Node *m_nextNode;
};
typedef struct t_Node* t_LinkedList;
void ListInsert(t_LinkedList* L, int position, int newData)
{
struct t_Node * newNode = malloc(sizeof(struct t_Node));
newNode -> m_Data = newData;
newNode -> m_nextNode = NULL;
if (!*L)
{
(*L) = newNode;
}
/* first Node is not NULL */
else
{
t_LinkedList anIterator;
anIterator = (*L);
if (!(*anIterator).m_nextNode)
{
(*anIterator).m_nextNode = newNode;
}
}
}
void printList(t_LinkedList list)
{
while(list != NULL)
{
printf("%d\n", list->m_Data);
list = list -> m_nextNode;
}
}
void deleteList(t_LinkedList list)
{
t_LinkedList node = list -> m_nextNode;
while(node)
{
free(list);
list = node;
node = node -> m_nextNode;
}
}
int main()
{
t_LinkedList aLinkedList;
aLinkedList = NULL;
ListInsert(&aLinkedList,1,10);
ListInsert(&aLinkedList,2,20);
printList(aLinkedList);
deleteList(aLinkedList);
return 0;
}

Linked list in c && use function to control

typedef struct LIST{
int count = 0;
}LIST;
typedef struct NODE{
int data;
struct NODE *link;
}NODE;
int main() {
NODE *p1, *p2, *p3;
p1 = (NODE*)malloc(sizeof(NODE));
p1->link = NULL;
p2 = (NODE*)malloc(sizeof(NODE));
p2->data = 20;
p2->link = NULL;
p1->link = p2;
I want to make add NODE function and list to control NODE.
Give me some answer to solve this problem.
you should define head in the list.
node * head;
Insert function as follows, to insert value in ascending order.
void insert(int val)
{
node * nd = new node();
nd->val = val;
if(head == NULL)
head = nd;
else
{
if(val <= head->val)
{
nd->next = head;
head = nd;
}
else
{
node * itr = head;
while(itr->next != NULL && itr->next->val <= val)
itr = itr->next;
nd->next = itr->next;
itr->next = nd;
}
}
}
First you probably want to add to your LIST struct a field "NODE *first", which points to NULL initially, and then will point to the first element of your list.
Then what does you add function should do? Add to the beginning or the end of the list?
If at the beginning: allocate a NODE, set its link pointer to the first element of your list and say that the first element of the list is now the node that you just allocated.
Try to give variable according to their work, so that it is easy to understand.
struct node
{
int val;
struct node* next;
};
void insert(struct node** head_ref, int data)
{
struct node* new_node = (struct node*)malloc(sizeof(struct node));
new_node->val = data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
int main()
{
struct node* head = NULL;
insert(&head,1);
insert(&head,2);
return 0;
}
Note that : Insert function will always add the value at front.
Try to write function for particular task.
I'll avoid giving you the entire answer in C code since it's in general better to "teach a man to fish".
I would suggest that you add a NODE * member to your LIST class to store the header node of your linked list.
The addNode that adds a node to the next node should look like this:
void addNode (LIST* list, NODE * penultNode, int newData);
// list: Address to the linked list info object
// penultNode: Address to the node after which you want to add a new node.
// Should be NULL if your linkedlist is empty
// newData: Data in the new node that you wanna add
Inside this function, your actions will depend on whether penultNode is NULL or not. If it is not null, your job is simple. You just allocate a new NODE object and set the pointer of penultNode->next to the new object. If it is NULL, that means that no node exists in the list yet. In this case, you will need to set the pointer of list->headerNode to the new NODE object.

Double linked list prepend element by ref in C

I try to write double linked list in C.
This is my implementation:
typedef struct
{
void* value;
struct Dlist* prev;
struct Dlist* next;
} Dlist;
Dlist* createDlist()
{
Dlist* newList = (Dlist*)malloc (sizeof(Dlist));
newList->value = NULL;
newList->next = NULL;
newList->prev = NULL;
return newList;
}
/*
* Get last element from Dlist
*/
Dlist* getLast(Dlist* list)
{
if (list)
{
while(list->next)
list = (Dlist*)list->next;
}
return list;
}
/*
* add element to list at start
*/
Dlist* addItemAtStart(Dlist* list, Pair* value)
{
Dlist* newList = NULL;
Dlist* last = NULL;
newList = createDlist ();
newList->value = value;
if (list)
{
last = getLast(list);
last->next = newList;
newList->prev = last;
return list;
}
else
return newList;
}
Now, when i try to add element to my list, i need assign a new value every time:
list = addItemAtStart(list, "Hello");
But i want only
addItemAtStart(list, "Hello");
Without list = How can i make so that list will change without assign?
p.s. I get segfaut with Dlist* addItemAtStart(Dlist **list, void* value)
I try to insert so:
Dlist **list = NULL;
addItemAtStart(&list, "Hello");
Thank you.
If you handle the list by pointing to its first element, maybe you should use double indirection:
void addItemAtStart(Dlist** plist, Pair* value)
{
// replace all list with *plist
}
addItemAtStart(&list, "Hello");
You can write your function to accept a pointer to a pointer to a List:
Dlist* addItemAtStart(Dlist** list, Pair* value)
Just make sure you add another level of indirection inside of addItemAtStart when using list.
The function can be called using
addItemAtStart(&list, "Hello");
Give reference of the head node to insert node at start.
Dlist* addItemAtStart(Dlist** list, Pair* value)
{
Dlist* newList = NULL;
Dlist* last = NULL;
newList = createDlist();
newList->value = value;
if (list)
{
last = getLast(*list);
last->next = newList;
newList->prev = last;
}
else
*list = newList
for achieving that, you need to create a static linked list node pointer.
make sure that the atitematstart method updates that node.
Using a global list will solve your problem. In the function, assign the value to the list object. I have tried it.
Your code with some corrections and inclusions:
#include <stdio.h>
#include <stdlib.h>
struct node{
void* value;
struct node *prev, *next;
};
/*This Function is Unnecessary
struct node * createList(){
struct node *newNode=malloc(sizeof(struct node));
if (newNode==NULL) return NULL;
newNode->value = NULL;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
*/
/*
*This Function is also Unnecessary
*Get last element from Dlist
struct node* getLast(struct node* node){
if (node==NULL) return NULL;
while (node->next!=NULL) node=node->next;
return node;
}
*/
/*
*Description: add element to list at start
*
*Return Values:
*0:Failed
*1:Succeeded
*/
int addItemAtStart(struct node **head, void *value){
struct node *newNode=malloc(sizeof(struct node));
/*Sometimes malloc can't allocate memory and returns NULL so you have to check it and if malloc couldn't allocate memory you have to exit the function*/
if (newNode==NULL) return 0;
newNode->value=value;
newNode->prev=NULL;
newNode->next=*head;
if (*head!=NULL) (*head)->prev=newNode;
*head=newNode;
return 1;
}
int main(){
struct node *list=NULL;
addItemAtStart(&list, "apple");
addItemAtStart(&list, "lemon");
addItemAtStart(&list, "orange");
addItemAtStart(&list, "peach");
return 0;
}

Removing node from singly linked list

I need to remove a node from a singly linked list. I know this is a simple thing to do, but my mind is blank and I've searched both Google and Stackoverflow, but I seriously haven't found anything that will help me.
basically the list of nodes is contained in a bucket; like this:
struct node{
unsigned char id[20];
struct node *next;
};
struct bucket{
unsigned char id;
struct node *nodes;
};
and I have a function
struct bucket *dht_bucketfind(unsigned char *id); // return bucket with id[20]
to find the correct bucket. So I know how to find the correct bucket, but I don't know how to remove a given node. I would like to remove the node by nodeid (I think, I haven't really written the code that will call the remove function yet ;) but I think I'll be able to modify the code if necessary). I think that's all that's needed to solve this. Thanks in advance.
If you know the item you want to remove, you must do two things:
Change all pointers that point to the target item to point to the target item's next member. This will be the preceding item's next pointer, or the head of the list bucket.nodes.
Free the node you just made unreachable.
The code for manipulating a linked list is really not that tricky, once you understand what you are doing.
Your nodes don't have any payload other than an id, so, depending on the data payload of a node, you might not actually need to iterate the list in the standard way. This is useful if deleters are going to know the address of only the node they want to delete.
If your payload is a pointer to other data:
struct _node {
void *data;
unsigned char id[20];
struct _node *next
}
Then you could "delete" a node by stealing the payload of the next node, and then delinking the next node:
int delete (struct _node *node)
{
struct _node *temp;
memcpy(node->id, node->next->id, 20);
free_function(node->data);
node->data = node->next->data;
temp = node->next;
node->next = node->next->next);
free(temp);
return 0;
}
/* define your two pointers, prev and cur */
prev=NULL;
cur=head;
/* traverse the list until you find your target */
while (cur != NULL && cur->id != search_id) {
prev=cur;
cur=cur->next;
}
/* if a result is found */
if (cur != NULL) {
/* check for the head of the list */
if (prev == NULL)
head=cur->next;
else
prev->next=cur->next;
/* release the old memory structure */
free(cur);
}
public void Remove(T data)
{
if (this.Head.Data.Equals(data))
{
this.Head = this.Head.Next;
this.Count = this.Count - 1;
}
else
{
LinkedListNode<T> node = this.Head;
bool found = false;
while (node.Next != null && !found)
{
if (node.Next.Data.Equals(data))
{
found = true;
node.Next = node.Next.Next;
this.Count = Count - 1;
}
else
{
node = node.Next;
}
}
}
}
Its been a long time ago since I worked with C, but this should be compile clean.
Basically, you need to keep track of the previous pointer while you iterate through the linked list. When you find the node to delete, just change the previous pointer to skip the delete node.
This function deletes all nodes with id (find). If you want to delete only the first occurrence, then put a return after the free statement.
void delete(struct bucket *thisBucket, unsigned char find[20]) {
struct node *prev = null;
struct node *curr = thisBucket->nodes;
while (curr != null) {
if (!strcmp(curr->id, find)) { // found the node?
if (prev == null) { // going to delete the first node (header)?
thisBucket->nodes = curr->next; // set the new header to the second node
} else {
prev->next = curr->next;
}
free(curr);
// if deleted the first node, then current is now the new header,
// else jump to the next
curr = prev == null? thisBucket->nodes : prev->next;
} else { // not found, keep going
prev = curr;
curr = curr->next;
}
}
}
The following does not contain any error checking and only removes the current node from the list ...
pPrev->next = pCurrent->next;
Your preferences may vary, but I tend to put my linked list node at the start of the structure (whenever practical).
struct node{
struct node *next;
unsigned char id[20];
};
struct bucket{
struct node *nodes;
unsigned char id;
};
I find this generally helps to simplify pointer arithmetic and allows simple typecasting when needed.
This removes a node given its address; you can modify it to remove a node given its id, but you haven't specified the form of an id -- is it a NUL-terminated string, or is it 20 bytes?
// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
struct node** ppnode = &bucket->nodes;
for( ;; ){
struct node* pnode = *ppnode;
if( pnode == NULL ) return 0;
if( pnode == node ){
*ppnode = pnode->next;
return 1;
}
ppnode = &pnode->next;
}
}
Or, more compactly,
// remove node from bucket and return true
// or return false if node isn't in bucket
int dht_rmnode(struct bucket* bucket, struct node* node)
{
struct node** ppnode = &bucket->nodes;
struct node* pnode;
for( ; (pnode = *ppnode); ppnode = &pnode->next )
if( pnode == node ){
*ppnode = pnode->next;
return 1;
}
return 0;
}
typedef struct node
{
int id;
struct node* next;
}Node;
void delete_element(void)
{
int i;
Node* current=head;
Node* brev=NULL;
if(i==head->id){
head=current->next;
free(current);}
else{
while(NULL!=current->next)
{
if(i==current->next->id){
brev=current;
current=current->next;
break;}
else
current=current->next;
}
if(i==current->id)
{
if(NULL==head->next){
head=NULL;
free(current);}
else
brev->next=current->next;
free(current);
}
else
printf("this id does not exist\n");
}
}

Resources