A simple (singly) linked list is a chain of nodes where each node stores two things: a value and a reference (pointer) to the next node in the sequence. The list is identified by a head pointer to the first node; the last node points to null (or None).
Unlike arrays, linked lists are not stored contiguously in memory. This makes inserting and removing elements simple when you know the relevant node, but accessing an element by index requires walking the list from the head.
value and next reference.null for an empty list).next is null on the last node.next pointer; doubly linked lists also have a prev pointer.tail pointer allows O(1) appends.Avoid a linked list when you need fast random access by index or tight cache locality; arrays or dynamic arrays may be better in those cases.
// Node structure (conceptual)
node {
value
next // reference to next node or null
}
// Insert at head
function push_front(ref head, value):
n = new node(value)
n.next = head
head = n
// Insert after a given node u
function insert_after(u, value):
if u is null: error
n = new node(value)
n.next = u.next
u.next = n
// Delete first node with matching value
function delete_first(ref head, value):
cur = head
prev = null
while cur != null and cur.value != value:
prev = cur
cur = cur.next
if cur == null: return false
if prev == null: head = cur.next
else: prev.next = cur.next
free(cur)
return true
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
void push_front(Node** head, int x) {
Node* n = (Node*)malloc(sizeof(Node));
n->data = x;
n->next = *head;
*head = n;
}
void push_back(Node** head, int x) {
Node* n = (Node*)malloc(sizeof(Node));
n->data = x; n->next = NULL;
if (!*head) { *head = n; return; }
Node* cur = *head;
while (cur->next) cur = cur->next;
cur->next = n;
}
bool delete_first(Node** head, int x) {
Node** cur = head;
while (*cur && (*cur)->data != x) cur = &(*cur)->next;
if (!*cur) return false;
Node* tmp = *cur;
*cur = tmp->next;
free(tmp);
return true;
}
void print_list(Node* head) {
for (Node* p = head; p; p = p->next) printf("%d -> ", p->data);
printf("NULL\n");
}
void free_list(Node* head) {
while (head) { Node* n = head; head = head->next; free(n); }
}
int main(void) {
Node* head = NULL;
push_front(&head, 3);
push_front(&head, 1);
push_back(&head, 5);
print_list(head); // 1 -> 3 -> 5 -> NULL
delete_first(&head, 3);
print_list(head); // 1 -> 5 -> NULL
free_list(head);
return 0;
}
class Node:
def __init__(self, data, nxt=None):
self.data = data
self.next = nxt
class SinglyList:
def __init__(self):
self.head = None
def push_front(self, x):
self.head = Node(x, self.head)
def append(self, x):
n = Node(x)
if not self.head:
self.head = n
return
cur = self.head
while cur.next:
cur = cur.next
cur.next = n
def delete_first(self, x):
cur, prev = self.head, None
while cur and cur.data != x:
prev, cur = cur, cur.next
if not cur:
return False
if prev is None:
self.head = cur.next
else:
prev.next = cur.next
return True
def __iter__(self):
cur = self.head
while cur:
yield cur.data
cur = cur.next
lst = SinglyList()
lst.push_front(3)
lst.push_front(1)
lst.append(5)
print(list(lst)) # [1, 3, 5]
lst.delete_first(3)
print(list(lst)) # [1, 5]