Delete from Position (Circular Linked List)
Deleting at index pos (0-based) reuses the same cases as the linear list: pos == 0 → delete from beginning; pos == n - 1 → delete from end; otherwise walk pos - 1 steps from head, unlink the next node, then free it. Invalid pos leaves the list unchanged.
C program (return tail)
The demo builds 10 20 30 with insert_end, then removes 20 at index 1, then 30, then 10—matching the flow in Delete from Position (SLL).
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *insert_end(struct Node *tail, int data)
{
struct Node *newNode = malloc(sizeof(struct Node));
if (newNode == NULL)
return tail;
newNode->data = data;
if (tail == NULL) {
newNode->next = newNode;
return newNode;
}
newNode->next = tail->next;
tail->next = newNode;
return newNode;
}
static int count_nodes(struct Node *tail)
{
if (tail == NULL)
return 0;
struct Node *h = tail->next;
struct Node *c = h;
int n = 0;
do {
n++;
c = c->next;
} while (c != h);
return n;
}
struct Node *delete_begin(struct Node *tail)
{
if (tail == NULL)
return NULL;
struct Node *head = tail->next;
if (head == tail) {
free(tail);
return NULL;
}
tail->next = head->next;
free(head);
return tail;
}
struct Node *delete_end(struct Node *tail)
{
if (tail == NULL)
return NULL;
struct Node *head = tail->next;
if (head == tail) {
free(tail);
return NULL;
}
struct Node *cur = head;
while (cur->next != tail)
cur = cur->next;
cur->next = tail->next;
free(tail);
return cur;
}
struct Node *delete_at(struct Node *tail, int pos)
{
if (tail == NULL)
return NULL;
int n = count_nodes(tail);
if (pos < 0 || pos >= n)
return tail;
if (pos == 0)
return delete_begin(tail);
if (pos == n - 1)
return delete_end(tail);
struct Node *head = tail->next;
struct Node *cur = head;
for (int i = 0; i < pos - 1; i++)
cur = cur->next;
struct Node *toRemove = cur->next;
cur->next = toRemove->next;
free(toRemove);
return tail;
}
void print_list(struct Node *tail)
{
if (tail == NULL) {
printf("\n");
return;
}
struct Node *head = tail->next;
struct Node *cur = head;
do {
printf("%d ", cur->data);
cur = cur->next;
} while (cur != head);
printf("\n");
}
int main(void)
{
struct Node *tail = NULL;
tail = insert_end(tail, 10);
tail = insert_end(tail, 20);
tail = insert_end(tail, 30);
print_list(tail); /* 10 20 30 */
tail = delete_at(tail, 1); /* remove 20 */
tail = delete_at(tail, 1); /* remove 30 */
tail = delete_at(tail, 0); /* remove 10 */
print_list(tail); /* empty list: newline only */
return 0;
}
Program output
10 20 30
First print_list shows the list. After three delete_at calls, the second print_list prints only a newline (no numbers).
Overall program flow
| Call | List before | Action | List after |
|---|---|---|---|
delete_at(tail, 1) | 10 20 30 | Middle delete → splice | 10 30 |
delete_at(tail, 1) | 10 30 | Ends → delete_end | 10 |
delete_at(tail, 0) | 10 | Ends → delete_begin (single node) | empty |
Complexity summary
| Case | Time |
|---|---|
| First / last index | O(1) or O(n) (see begin/end pages) |
| Middle index | O(pos) walk + O(1) unlink |
See also Delete from Position (SLL) · Insert at Position (CLL)