Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ds/xor_list/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
all:
cc -o main main.c && ./main

clean:
rm -f main
61 changes: 61 additions & 0 deletions ds/xor_list/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "xor_list.h"

#include <stdio.h>

struct book {
int id;
char name[50];
xor_list_node_t node;
};

int match_id(xor_list_node_t *n, void *arg)
{
struct book *b = container_of(n, struct book, node);
return b->id == *(int *)arg;
}

int main() {
xor_list_t list;
xor_list_init(&list);

struct book a = { .id = 1, .name = "西游记" };
struct book b = { .id = 2, .name = "红楼梦" };
struct book c = { .id = 3, .name = "三国演义" };
struct book d = { .id = 4, .name = "水浒传" };
xor_list_append(&list, &a.node);
xor_list_append(&list, &b.node);
xor_list_append(&list, &c.node);
xor_list_append(&list, &d.node);

xor_list_node_t *pos, *prev, *next;
printf("\n----for_each forward----\n");
xor_list_for_each(pos, prev, &list) {
struct book *it = container_of(pos, struct book, node);
printf("[%d] 《%s》\n", it->id, it->name);
}
printf("\n----for_each reverse----\n");
xor_list_for_each_reverse(pos, next, &list) {
struct book *it = container_of(pos, struct book, node);
printf("[%d] 《%s》\n", it->id, it->name);
}

struct book e = { 5, "聊斋志异" };
struct book f = { 6, "老子" };
int key = 3;
pos = xor_list_find(&list, match_id, &key, &prev);
if (pos) {
xor_list_add_after(&list, pos, prev, &e.node);
xor_list_add_after(&list, pos, prev, &f.node);
}
printf("\n----add_before_(id=%d)_after----\n", key);
xor_list_for_each(pos, prev, &list) {
struct book *it = container_of(pos, struct book, node);
printf("[%d] 《%s》\n", it->id, it->name);
}
printf("\n----reverse add_before_(id=%d)_after----\n", key);
xor_list_for_each_reverse(pos, next, &list) {
struct book *it = container_of(pos, struct book, node);
printf("[%d] 《%s》\n", it->id, it->name);
}
return 0;
}
145 changes: 145 additions & 0 deletions ds/xor_list/xor_list.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#ifndef _XOR_LIST_H
#define _XOR_LIST_H

#include <stdint.h>
#include <stddef.h>

// XOR Linked List Implementation
// Inspired by Tsoding

typedef struct xor_list_node {
uintptr_t npx;
} xor_list_node_t;

typedef struct xor_list {
xor_list_node_t *head;
xor_list_node_t *tail;
} xor_list_t;

static inline xor_list_node_t *
xor_node(xor_list_node_t *a, xor_list_node_t *b)
{
return (xor_list_node_t *)((uintptr_t)a ^ (uintptr_t)b);
}

static inline xor_list_node_t *
xor_list_next(xor_list_node_t *curr, xor_list_node_t *prev)
{
return xor_node((xor_list_node_t *)curr->npx, prev);
}

static inline void
xor_list_init(xor_list_t *l)
{
l->head = NULL;
l->tail = NULL;
}

static inline int
xor_list_empty(const xor_list_t *l)
{
return l->head == NULL;
}

static inline void
xor_list_node_init(xor_list_node_t *n)
{
n->npx = 0;
}

static inline void
xor_list_append(xor_list_t *l, xor_list_node_t *n)
{
xor_list_node_init(n);
n->npx = (uintptr_t)l->tail;
if (l->tail) {
l->tail->npx ^= (uintptr_t)n;
} else {
l->head = n;
}
l->tail = n;
}

static inline void
xor_list_prepend(xor_list_t *l, xor_list_node_t *n)
{
xor_list_node_init(n);
n->npx = (uintptr_t)l->head;
if (l->head) {
l->head->npx ^= (uintptr_t)n;
} else {
l->tail = n;
}
l->head = n;
}

static inline void
xor_list_add_before(xor_list_t *l, xor_list_node_t *pos, xor_list_node_t *prev, xor_list_node_t *n)
{
xor_list_node_t *next;
next = xor_list_next(pos, prev);
xor_list_node_init(n);
n->npx = (uintptr_t)prev ^ (uintptr_t)pos;
prev->npx ^= (uintptr_t)pos ^ (uintptr_t)n;
pos->npx ^= (uintptr_t)prev ^ (uintptr_t)n;
}

static inline void
xor_list_add_after(xor_list_t *l, xor_list_node_t *pos, xor_list_node_t *prev, xor_list_node_t *n)
{
xor_list_node_t *next;
next = xor_list_next(pos, prev);
xor_list_node_init(n);
n->npx = (uintptr_t)pos ^ (uintptr_t)next;
pos->npx ^= (uintptr_t)next ^ (uintptr_t)n;
if (next) {
next->npx ^= (uintptr_t)pos ^ (uintptr_t)n;
} else {
l->tail = n;
}
}

static inline xor_list_node_t *
xor_list_find(xor_list_t *l, int (*pred)(xor_list_node_t *n, void *arg), void *arg, xor_list_node_t **out_prev)
{
xor_list_node_t *curr = l->head;
xor_list_node_t *prev = NULL;
while (curr) {
if (pred(curr, arg)) {
if (out_prev)
*out_prev = prev;
return curr;
}
xor_list_node_t *next = xor_list_next(curr, prev);
prev = curr;
curr = next;
}
return NULL;
}

#define xor_list_for_each(pos, prev, list) \
for ((prev) = NULL, (pos) = (list)->head; \
(pos) != NULL; \
({ \
xor_list_node_t *next = \
xor_list_next((pos), (prev)); \
(prev) = (pos); \
(pos) = next; \
}))

#define xor_list_for_each_reverse(pos, next, list) \
for ((next) = NULL, (pos) = (list)->tail; \
(pos) != NULL; \
({ \
xor_list_node_t *prev = \
xor_list_next((pos), (next)); \
(next) = (pos); \
(pos) = prev; \
}))

#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); \
})

#endif /* _XOR_LIST_H */