list.h
struct list_head {
struct list_head *prev;
struct list_head *next;
};
#define LIST_HEAD(head) struct list_head head = {&head, &head}
static inline void INIT_LIST_HEAD(struct list_head *node)
{
node->prev = node;
node->next = node;
}
static inline void __list_add(struct list_head *node,
struct list_head *prev,
struct list_head *next)
{
node->prev = prev;
node->next = next;
prev->next = node;
next->prev = node;
}
static inline void list_add(struct list_head *node,
struct list_head *head)
{
__list_add(node, head, head->next);
}
static inline void list_add_tail(struct list_head *node,
struct list_head *head)
{
__list_add(node, head->prev, head);
}
static inline int list_emtpy(struct list_head *head)
{
return head->next == head;
}
static inline void list_del(struct list_head *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
static inline void list_del_init(struct list_head *node)
{
list_del(node);
INIT_LIST_HEAD(node);
}
#define offsetof(type, member) \
((size_t)(&((type*)0)->member))
#define container_of(ptr, type, member) \
({const typeof(((type*)0)->member) *__mptr = ptr; \
(type*)((char*)__mptr - offsetof(type, member));})
/* @cur: ?..list_head?..?.复?舵.?
* @head: 澶磋.?圭.?板.
*/
#define list_for_each(cur, head) \
for (cur = (head)->next; \
(cur) != (head); \
cur = (cur)->next)
/* @cur: ?..list_head?..?.复?舵.?
* @tmp: ?..cur涓.?涓..?圭.涓存.?..
* @head: 澶磋.?圭.?板.
*/
#define list_for_each_safe(cur, tmp, head) \
for (cur = (head)->next, tmp = (cur)->next; \
(cur) != (head); \
cur = tmp, tmp = (tmp)->next)
/* @ptr: ?..list_head?..??ㄧ.澶х??.??..?.复?舵.?
* @head: 澶磋.?圭.?板.
*/
#define list_for_each_entry(ptr, head, member) \
for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \
&(ptr)->member != (head); \
ptr = container_of((ptr)->member.next, typeof(*(ptr)), member) )
#define list_for_each_entry_safe(ptr, tmp, head, member) \
for ( ptr = container_of((head)->next, typeof(*(ptr)), member); \
(&(ptr)->member != (head)) && (tmp = container_of((ptr)->member.next, typeof(*(ptr)), member)); \
ptr = tmp )
#define list_for_each_continue(cur, head) \
for (cur = (cur)->next; \
(cur) != (head); \
cur = (cur)->next)
#define list_for_each_continue_safe(cur, tmp, head) \
for (cur = (cur)->next, tmp = (cur)->next; \
(cur) != (head); \
cur = tmp, tmp = (tmp)->next)
#define list_for_each_reverse(cur, head) \
for (cur = (head)->prev; \
(cur) != (head); \
cur = (cur)->prev)
#define list_for_each_reverse_continue(cur, head) \
for (cur = (cur)->prev; \
(cur) != (head); \
cur = (cur)->prev)
struct hlist_node {
struct hlist_node *next;
struct hlist_node **pprev;
};
struct hlist_head {
struct hlist_node *first;
};
#define HLIST_HEAD(head) struct hlist_head head = {NULL}
static inline void INIT_HLIST_HEAD(struct hlist_head *head)
{
head->first = NULL;
}
static inline void INIT_HLIST_NODE(struct hlist_node *node)
{
node->next = NULL;
node->pprev = NULL;
}
static inline void hlist_add_head(struct hlist_node *node,
struct hlist_head *head)
{
node->next = head->first;
node->pprev = &head->first;
head->first = node;
if (node->next) {
node->next->pprev = &node->next;
}
}
static inline void hlist_add_before(struct hlist_node *node, struct hlist_node *next)
{
node->next = next;
node->pprev = next->pprev;
*node->pprev = node;
next->pprev = &node->next;
}
static inline void hlist_add_after(struct hlist_node *prev,
struct hlist_node *node)
{
node->next = prev->next;
node->pprev = &prev->next;
prev->next = node;
if (node->next) {
node->next->pprev = &node->next;
}
}
static inline void hlist_del(struct hlist_node *node)
{
*node->pprev = node->next;
if (node->next) {
node->next->pprev = node->pprev;
}
}
static inline void hlist_del_init(struct hlist_node *node)
{
hlist_del(node);
INIT_HLIST_NODE(node);
}
static inline int hlist_empty(struct hlist_head *head)
{
return head->first == NULL;
}
#define hlist_for_each(cur, head) \
for (cur = (head)->first; \
cur; cur = (cur)->next)
#define hlist_for_each_safe(cur, tmp, head) \
for (cur = (head)->first; \
cur && ({tmp = (cur)->next; 1;}); \
cur = tmp)
#define hlist_for_each_continue(cur, head) \
for (cur = (cur)->next; \
cur; cur = (cur)->next)
#define hlist_for_each_from(cur, head) \
for (; cur; cur = (cur)->next)
#define hlist_for_each_entry(ptr, cur, head, member) \
for (cur = (head)->first; \
cur && (ptr = container_of(cur, typeof(*(ptr)), member)); \
cur = (cur)->next)
#define hlist_for_each_entry_safe(ptr, cur, tmp, head, member) \
for (cur = (head)->first; \
cur && (tmp = (cur)->next, 1) && \
(ptr = container_of(cur, typeof(*(ptr)), member)); \
cur = tmp)
sort.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG
#ifdef DEBUG
#define DBG_PRT(fmt, arg...) printf(fmt, arg);
#else
#define DBG_PRT(fmt, arg...)
#endif
struct data_info {
int data;
};
static void print_array(const void *s, size_t nmemb);
#define ELEM(n) ((char*)base + size * (n))
#define BIG_SWAP_SIZE 512
static void swap(void *a, void *b, size_t size)
{
char *tmp = (char*)malloc(size);
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
free(tmp);
}
static void select_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
size_t i = 0;
size_t j = 0;
size_t min = 0;
for (i = 0; i < nmemb - 1; ++i) {
min = i;
for (j = i + 1; j < nmemb; ++j) {
if (cmp(ELEM(min), ELEM(j)) > 0) {
min = j;
}
}
if (min != i) {
swap(ELEM(min), ELEM(i), size);
}
}
}
static void bubble_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
size_t i = 0;
size_t j = 0;
for (i = 1; i < nmemb; ++i) {
for (j = 0; j < nmemb - i; ++j) {
if (cmp(ELEM(j), ELEM(j+1)) > 0) {
swap(ELEM(j), ELEM(j+1), size);
}
}
}
}
static void insert_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
size_t i = 0;
ssize_t j = 0;
char *tmp = NULL;
tmp = (char*)malloc(size);
for (i = 1; i < nmemb; ++i) {
if (cmp(ELEM(i), ELEM(i-1)) >= 0) {
continue;
}
memcpy(tmp, ELEM(i), size);
for (j = i - 1; j >= 0; --j) {
if (cmp(tmp, ELEM(j)) < 0) {
memcpy(ELEM(j+1), ELEM(j), size);
} else {
memcpy(ELEM(j+1), tmp, size);
break;
}
}
//i?..??..绱..姣.澶э?姝ゆ.i搴..?ュ.0?峰.绱..浣.疆
if (j < 0) {
memcpy(ELEM(0), tmp, size);
}
}
free(tmp);
}
static void shell_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
size_t i = 0;
ssize_t j = 0;
char *tmp = (char*)malloc(size);
ssize_t step = 0;
ssize_t offset = 0;
for (step = 3; step >= 1; --step) {
for (offset = 0; offset < step; ++offset) {
//?..?.?
print_array(base, nmemb);
for (i = offset + step; i < nmemb; i += step) {
if (cmp(ELEM(i), ELEM(i-step)) >= 0) {
continue;
}
memcpy(tmp, ELEM(i), size);
for (j = i - step; j >= offset; j -= step) {
if (cmp(tmp, ELEM(j)) < 0) {
memcpy(ELEM(j+step), ELEM(j), size);
} else {
memcpy(ELEM(j+step), tmp, size);
break;
}
}
//i?..??..绱..姣.澶э?姝ゆ.i搴..?ュ.0?峰.绱..浣.疆
if (j < offset) {
memcpy(ELEM(offset), tmp, size);
}
}
} //endof offset
} //endof k
free(tmp);
}
static void merge_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
if (nmemb > 2) {
merge_sort(base, nmemb / 2, size, cmp);
merge_sort(ELEM(nmemb / 2), nmemb - nmemb / 2, size, cmp);
} else if (nmemb < 2) {
return;
}
char *s = (char*)malloc(nmemb * size);
size_t l = 0;
size_t r = nmemb / 2;
size_t s_offset = 0;
for (; (l < nmemb / 2) && (r < nmemb); ++s_offset) {
if (cmp(ELEM(l), ELEM(r)) <= 0) {
memcpy(s + s_offset * size , ELEM(l), size);
++l;
} else {
memcpy(s + s_offset * size, ELEM(r), size);
++r;
}
}
if (l < nmemb / 2) {
memcpy(s + s_offset * size, ELEM(l), (nmemb / 2 - l) * size);
} else {
memcpy(s + s_offset * size, ELEM(r), (nmemb - r) * size);
}
memcpy(base, s, nmemb * size);
free(s);
}
static void quick_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
if (nmemb < 2) {
return;
}
size_t l = 0;
size_t r = nmemb - 1;
//浠诲.涓涓..绱.?涓?ivot
size_t ipivot = nmemb / 2;
char *pivot = (char*)malloc(size);
memcpy(pivot, ELEM(ipivot), size);
print_array(base, nmemb);
printf("pivot=%d\n", ((struct data_info*)pivot)->data);
for (; (cmp(ELEM(l), pivot) <= 0) && (l < ipivot); ++l) {}
if (l < ipivot) {
memcpy(ELEM(ipivot), ELEM(l), size);
}
while (l < r) {
for (; (cmp(ELEM(r), pivot) >= 0) && (l < r); --r) {}
if (l < r) {
memcpy(ELEM(l), ELEM(r), size);
++l;
} else {
break;
}
for (; (cmp(ELEM(l), pivot) <= 0) && (l < r); ++l) {}
if (l < r) {
memcpy(ELEM(r), ELEM(l), size);
--r;
}
}
memcpy(ELEM(l), pivot, size);
free(pivot);
print_array(base, nmemb);
quick_sort(base, l, size, cmp);
quick_sort(ELEM(l+1), nmemb - l - 1, size, cmp);
}
static void __check_heap(void *base, size_t nmemb,
size_t size, size_t cur,
int (*cmp)(const void *, const void *))
{
#define LCHILD(n) (2 * (n) + 1)
#define RCHILD(n) (2 * (n) + 2)
size_t max_child = 0;
while (LCHILD(cur) < nmemb) { //?..瀛..?
if ((RCHILD(cur) < nmemb)
&& (cmp(ELEM(LCHILD(cur)), ELEM(RCHILD(cur))) < 0)) {
max_child = RCHILD(cur);
} else {
max_child = LCHILD(cur);
}
if (cmp(ELEM(max_child), ELEM(cur)) > 0) {
swap(ELEM(max_child), ELEM(cur), size);
cur = max_child;
} else {
break;
}
}
}
static void heap_sort(void *base, size_t nmemb,
size_t size,
int (*cmp)(const void *, const void *))
{
//?.钩?存5?
//?惧.??.?涓..?跺.?..?.??
size_t cur = 0;
if (nmemb % 2) {
cur = (nmemb - 3) / 2;
} else {
cur = (nmemb - 2) / 2;
}
for (; cur > 0; --cur) {
__check_heap(base, nmemb, size, cur, cmp);
}
//?.?
for (; nmemb > 1; --nmemb) {
__check_heap(base, nmemb, size, 0, cmp);
swap(ELEM(0), ELEM(nmemb-1), size);
}
}
static void print_array(const void *s, size_t nmemb)
{
size_t i = 0;
for (i = 0; i < nmemb; ++i) {
printf("%d ", ((struct data_info *)s)[i].data);
}
printf("\n");
}
static int cmp(const void *a, const void *b)
{
return ((struct data_info*)a)->data - ((struct data_info*)b)->data;
}
int main()
{
struct data_info s[] = {
{5}, {6}, {1}, {-9}, {0}, {6}, {7}, {2}, {4}, {-2}, {5}, {-1}, {15}, {19}, {7},
};
void (*sort[])(void*, size_t, size_t,
int (*)(const void*, const void*)) = {
select_sort, //0
bubble_sort, //1
insert_sort, //2
shell_sort, //3
merge_sort, //4
quick_sort, //5
heap_sort, //6
};
sort[6](s, sizeof(s) / sizeof(struct data_info),
sizeof(struct data_info), cmp);
print_array(s, sizeof(s) / sizeof(struct data_info));
return 0;
}
sort_list.c
#include <stdio.h>
#include "list.h"
struct data_info {
ssize_t data;
struct list_head list;
};
static void swap(struct list_head *a, struct list_head *b)
{
LIST_HEAD(tmp);
__list_add(&tmp, a, a->next);
list_del(a);
__list_add(a, b, b->next);
list_del(b);
__list_add(b, tmp.prev, &tmp);
list_del(&tmp);
}
static void select_sort(struct list_head *head,
int (*cmp)(struct list_head *,
struct list_head *))
{
struct list_head *min = NULL;
struct list_head *i = NULL;
struct list_head *j = NULL;
struct list_head *tmp = NULL;
list_for_each_safe(i, tmp, head) {
min = i;
j = i;
list_for_each_continue(j, head) {
if (cmp(min, j) > 0) {
min = j;
}
}
if (min != i) {
swap(min, i);
}
}
}
static void bubble_sort(struct list_head *head,
int (*cmp)(struct list_head *,
struct list_head *))
{
struct list_head *i = NULL;
struct list_head *j = NULL;
list_for_each_reverse(i, head) {
list_for_each(j, head) {
if (j == i) {
break;
}
if (cmp(j, j->next) > 0) {
swap(j, j->next);
j = j->prev;
if (i == j) {
i = i->next;
}
}
}
}
}
static void insert_sort(struct list_head *head,
int (*cmp)(struct list_head *,
struct list_head *))
{
struct list_head *i = head->next;
struct list_head *j = NULL;
struct list_head *tmp = NULL;
list_for_each_continue_safe(i, tmp, head) {
j = i;
if (cmp(i, i->prev) >= 0) {
continue;
} else {
list_del(i);
}
list_for_each_reverse_continue(j, head) {
if (cmp(i, j) >= 0) {
__list_add(i, j, j->next);
break;
}
}
if (j == head) {
list_add(i, head);
}
}
}
static int cmp(struct list_head *a, struct list_head *b)
{
struct data_info *pa = container_of(a, struct data_info, list);
struct data_info *pb = container_of(b, struct data_info, list);
return pa->data - pb->data;
}
int main()
{
struct data_info s[] = {
{5}, {6}, {1}, {-9}, {0}, {6}, {7}, {2}, {4}, {-2}, {5}, {-1}, {15}, {19}, {7},
};
LIST_HEAD(head);
size_t i = 0;
for (i = 0; i < sizeof(s) / sizeof(struct data_info); ++i) {
list_add_tail(&s[i].list, &head);
}
insert_sort(&head, cmp);
struct data_info *ptr = NULL;
list_for_each_entry(ptr, &head, list) {
printf("%ld ", ptr->data);
}
printf("\n");
return 0;
}