diff --git a/Chapter11/ds/line/list/linklist/double/kernel/list.h b/Chapter11/ds/line/list/linklist/double/kernel/list.h new file mode 100644 index 0000000..1d87fe2 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/kernel/list.h @@ -0,0 +1,56 @@ +#ifndef LINUX_LIST_H__ +#define LINUX_LIST_H__ + +struct list_head +{ + struct list_head *prev; + struct list_head *next; +}; + +#define LIST_HEAD_INIT(name) \ + { \ + &(name), &(name) \ + } + +#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) + +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +// 这个内核的链表仅包含两个指针,用来被数据包含 +// 希望由嵌入的指针找回到完整的结构体 + +/** + * ptr->cur + * type->struct score_st + * member->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)); \ + }) + +#define list_entry(ptr, type, member) container_of(ptr, type, member) + +#endif \ No newline at end of file diff --git a/Chapter11/ds/line/list/linklist/double/kernel/main.c b/Chapter11/ds/line/list/linklist/double/kernel/main.c new file mode 100644 index 0000000..77bfb7a --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/kernel/main.c @@ -0,0 +1,63 @@ +#include +#include + +#include "list.h" + +#define NAMESIZE 32 + +struct score_st +{ + int id; + char name[NAMESIZE]; + struct list_head node; + int math; + int chinese; +}; + +static void print_s(struct score_st *d) +{ + printf("%d %s %d %d \n", d->id, d->name, d->math, d->chinese); +} + +int main() +{ + int i; + struct score_st *datap; + struct list_head *cur; + + LIST_HEAD(head); + + for (i = 0; i < 7; i++) + { + datap = malloc(sizeof(*datap)); + if (NULL == datap) + exit(1); + + datap->id = i; + snprintf(datap->name, NAMESIZE, "stu%d", i); + datap->math = rand() % 100; + datap->chinese = rand() % 100; + + list_add(&datap->node, &head); + } + + __list_for_each(cur, &head) + { + datap = list_entry(cur, struct score_st, node); + print_s(datap); + } + + + __list_for_each(cur, &head) + { + datap = list_entry(cur, struct score_st, node); + if (5 == datap->id) + break; + } + if (cur == &head) + printf("Can not find!\n"); + else + print_s(datap); + + exit(0); +} \ No newline at end of file diff --git a/Chapter11/ds/line/list/linklist/double/kernel/makefile b/Chapter11/ds/line/list/linklist/double/kernel/makefile new file mode 100644 index 0000000..a7681ed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/kernel/makefile @@ -0,0 +1,31 @@ +# 方便起见一般都会先定义编译器链接器 +CC = gcc +LD = gcc + +# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c +SRCS = $(wildcard *.c) + +# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o +OBJS = $(patsubst %c, %o, $(SRCS)) + +# 可执行文件的名字 +TARGET = main + +# .PHONE伪目标,具体含义百度一下一大堆介绍 +.PHONY:all clean + +# 要生成的目标文件 +all: $(TARGET) + +# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o +# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 +$(TARGET): $(OBJS) + $(LD) -o $@ $^ + +# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 +%.o:%.c + $(CC) -c $^ + +# make clean删除所有.o和目标文件 +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Chapter11/ds/line/list/linklist/double/lib1/Makefile b/Chapter11/ds/line/list/linklist/double/lib1/Makefile new file mode 100644 index 0000000..a7681ed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib1/Makefile @@ -0,0 +1,31 @@ +# 方便起见一般都会先定义编译器链接器 +CC = gcc +LD = gcc + +# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c +SRCS = $(wildcard *.c) + +# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o +OBJS = $(patsubst %c, %o, $(SRCS)) + +# 可执行文件的名字 +TARGET = main + +# .PHONE伪目标,具体含义百度一下一大堆介绍 +.PHONY:all clean + +# 要生成的目标文件 +all: $(TARGET) + +# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o +# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 +$(TARGET): $(OBJS) + $(LD) -o $@ $^ + +# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 +%.o:%.c + $(CC) -c $^ + +# make clean删除所有.o和目标文件 +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Chapter11/ds/line/list/linklist/double/lib1/llist.c b/Chapter11/ds/line/list/linklist/double/lib1/llist.c new file mode 100644 index 0000000..2ec3aed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib1/llist.c @@ -0,0 +1,134 @@ +#include +#include +#include + +#include "llist.h" + +LLIST *llist_create(int initsize) +{ + LLIST *new; + + new = malloc(sizeof(*new)); // !!! 不是sizeof(initsize),也不是new,是*new + if (NULL == new) + return NULL; + + new->size = initsize; + new->head.data = NULL; + new->head.prev = &new->head; + new->head.next = &new->head; + + return new; +} + +int llist_insert(LLIST *ptr, const void *data, int mode) +{ + struct llist_node_st *newnode; + + newnode = malloc(sizeof(*newnode)); + if (NULL == newnode) + return -1; + + newnode->data = malloc(ptr->size); + if (newnode->data == NULL) + return -2; + + memcpy(newnode->data, data, ptr->size); + + if (LLIST_FORWARD == mode) + { + newnode->prev = &ptr->head; + newnode->next = ptr->head.next; + } + else if (LLIST_BACKWARD == mode) + { + newnode->prev = ptr->head.prev; + newnode->next = &ptr->head; + } + else // error + { + return -3; + } + + // !!! 妙啊 + newnode->next->prev = newnode; + newnode->prev->next = newnode; + + return 0; +} + +static struct llist_node_st *find_(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + { + if (0 == cmp(key, cur->data)) + break; + } + + return cur; // 找不到的时候,返回的cur就是ptr,返回NULL +} + +void *llist_find(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + return find_(ptr, key, cmp)->data; +} + +int llist_delete(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + // !!! + node->prev->next = node->next; + node->next->prev = node->prev; + free(node->data); + free(node); + + return 0; +} + +int llist_fetch(LLIST *ptr, const void *key, llist_cmp *cmp, void *data) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + node->next->prev = node->prev; + node->prev->next = node->next; + + if (data != NULL) + memcpy(data, node->data, ptr->size); + + free(node->data); + free(node); + + return 0; +} + +void llist_travel(LLIST *ptr, llist_op *op) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + op(cur->data); +} + +void llist_destroy(LLIST *ptr) +{ + struct llist_node_st *cur, *next; + + for (cur = ptr->head.next; cur != &ptr->head; cur = next) + { + next = cur->next; + free(cur->data); + free(cur); + } + + free(ptr); +} diff --git a/Chapter11/ds/line/list/linklist/double/lib1/llist.h b/Chapter11/ds/line/list/linklist/double/lib1/llist.h new file mode 100644 index 0000000..25178a9 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib1/llist.h @@ -0,0 +1,37 @@ +#ifndef LLIST_H__ +#define LLIST_H__ + +#define LLIST_FORWARD 1 +#define LLIST_BACKWARD 2 + +struct llist_node_st +{ + void *data; + struct llist_node_st *prev; + struct llist_node_st *next; +}; + +typedef struct +{ + int size; + struct llist_node_st head; +} LLIST; + +typedef void llist_op(const void *); +typedef int llist_cmp(const void *, const void *); + +LLIST *llist_create(int initsize); + +int llist_insert(LLIST *ptr, const void *data, int mode); + +void *llist_find(LLIST *ptr, const void *key, llist_cmp *); + +int llist_delete(LLIST *, const void *key, llist_cmp *); + +int llist_fetch(LLIST *, const void *key, llist_cmp *, void *data); + +void llist_travel(LLIST *ptr, llist_op *op); + +void llist_destroy(LLIST *ptr); + +#endif diff --git a/Chapter11/ds/line/list/linklist/double/lib1/main.c b/Chapter11/ds/line/list/linklist/double/lib1/main.c new file mode 100644 index 0000000..e736037 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib1/main.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "llist.h" + +#define NAMESIZE 32 + +struct score_st +{ + int id; + char name[NAMESIZE]; + int math; + int chinese; +}; + +void print_s(const void *record) +{ + const struct score_st *r = record; + + printf("%d %s %d %d\n", r->id, r->name, r->math, r->chinese); +} + +int id_cmp(const void *key, const void *record) +{ + const int *k = key; + const struct score_st *r = record; + + return (*k - r->id); +} + +int name_cmp(const void *key, const void *record) +{ + const char *k = key; + const struct score_st *r = record; + + return strcmp(k, r->name); +} + + +int main() +{ + LLIST *handler; + int i, ret; + struct score_st tmp; + + handler = llist_create(sizeof(struct score_st)); + if (NULL == handler) + exit(1); + + for (i = 0; i < 7; i++) + { + tmp.id = i; + snprintf(tmp.name, NAMESIZE, "std%d", i); + tmp.math = rand() % 100; + tmp.chinese = rand() % 100; + + ret = llist_insert(handler, &tmp, LLIST_FORWARD); + if (ret) + exit(1); + } + + llist_travel(handler, print_s); + + printf("\n\n"); + + // int id = 3; + char *del_name = "std6"; + + // ret = llist_delete(handler, &id, id_cmp); + ret = llist_delete(handler, del_name, name_cmp); + if (ret) + printf("llist_deleter failed!\n"); + + llist_travel(handler, print_s); + + + +#if 0 + int id = 3; + struct score_st *data; + + data = llist_find(handler, &id, id_cmp); + if (NULL == data) + printf("Can not find!\n"); + else + print_s(data); + +#endif + + + llist_destroy(handler); + + exit(0); +} \ No newline at end of file diff --git a/Chapter11/ds/line/list/linklist/double/lib2/Makefile b/Chapter11/ds/line/list/linklist/double/lib2/Makefile new file mode 100644 index 0000000..a7681ed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib2/Makefile @@ -0,0 +1,31 @@ +# 方便起见一般都会先定义编译器链接器 +CC = gcc +LD = gcc + +# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c +SRCS = $(wildcard *.c) + +# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o +OBJS = $(patsubst %c, %o, $(SRCS)) + +# 可执行文件的名字 +TARGET = main + +# .PHONE伪目标,具体含义百度一下一大堆介绍 +.PHONY:all clean + +# 要生成的目标文件 +all: $(TARGET) + +# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o +# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 +$(TARGET): $(OBJS) + $(LD) -o $@ $^ + +# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 +%.o:%.c + $(CC) -c $^ + +# make clean删除所有.o和目标文件 +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Chapter11/ds/line/list/linklist/double/lib2/llist.c b/Chapter11/ds/line/list/linklist/double/lib2/llist.c new file mode 100644 index 0000000..1190181 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib2/llist.c @@ -0,0 +1,130 @@ +#include +#include +#include + +#include "llist.h" + +LLIST *llist_create(int initsize) +{ + LLIST *new; + + new = malloc(sizeof(*new)); // !!! 不是sizeof(initsize),也不是new,是*new + if (NULL == new) + return NULL; + + new->size = initsize; + new->head.prev = &new->head; + new->head.next = &new->head; + + return new; +} + +int llist_insert(LLIST *ptr, const void *data, int mode) +{ + struct llist_node_st *newnode; + + newnode = malloc(sizeof(*newnode) + ptr->size); // -4 + if (NULL == newnode) + return -1; + + memcpy(newnode->data, data, ptr->size); + + if (LLIST_FORWARD == mode) + { + newnode->prev = &ptr->head; + newnode->next = ptr->head.next; + } + else if (LLIST_BACKWARD == mode) + { + newnode->prev = ptr->head.prev; + newnode->next = &ptr->head; + } + else // error + { + return -3; + } + + // !!! 妙啊 + newnode->next->prev = newnode; + newnode->prev->next = newnode; + + return 0; +} + +static struct llist_node_st *find_(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + { + if (0 == cmp(key, cur->data)) + break; + } + + return cur; // 找不到的时候,返回的cur就是ptr,返回NULL +} + +void *llist_find(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *node; + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return NULL; + + return node->data; +} + +int llist_delete(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + // !!! + node->prev->next = node->next; + node->next->prev = node->prev; + free(node); + return 0; +} + +int llist_fetch(LLIST *ptr, const void *key, llist_cmp *cmp, void *data) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + node->next->prev = node->prev; + node->prev->next = node->next; + + if (data != NULL) + memcpy(data, node->data, ptr->size); + + free(node); + + return 0; +} + +void llist_travel(LLIST *ptr, llist_op *op) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + op(cur->data); +} + +void llist_destroy(LLIST *ptr) +{ + struct llist_node_st *cur, *next; + + for (cur = ptr->head.next; cur != &ptr->head; cur = next) + { + next = cur->next; + free(cur); + } + + free(ptr); +} diff --git a/Chapter11/ds/line/list/linklist/double/lib2/llist.h b/Chapter11/ds/line/list/linklist/double/lib2/llist.h new file mode 100644 index 0000000..48457e4 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib2/llist.h @@ -0,0 +1,39 @@ +#ifndef LLIST_H__ +#define LLIST_H__ + +#define LLIST_FORWARD 1 +#define LLIST_BACKWARD 2 + +// !!! 变长结构体 +struct llist_node_st +{ + struct llist_node_st *prev; + struct llist_node_st *next; + // data要放在最后 + char data[1]; // 占位符,数据的起始。C99才只是[0] +}; + +typedef struct +{ + int size; + struct llist_node_st head; +} LLIST; + +typedef void llist_op(const void *); +typedef int llist_cmp(const void *, const void *); + +LLIST *llist_create(int initsize); + +int llist_insert(LLIST *ptr, const void *data, int mode); + +void *llist_find(LLIST *ptr, const void *key, llist_cmp *); + +int llist_delete(LLIST *, const void *key, llist_cmp *); + +int llist_fetch(LLIST *, const void *key, llist_cmp *, void *data); + +void llist_travel(LLIST *ptr, llist_op *op); + +void llist_destroy(LLIST *ptr); + +#endif diff --git a/Chapter11/ds/line/list/linklist/double/lib2/main.c b/Chapter11/ds/line/list/linklist/double/lib2/main.c new file mode 100644 index 0000000..e736037 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib2/main.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "llist.h" + +#define NAMESIZE 32 + +struct score_st +{ + int id; + char name[NAMESIZE]; + int math; + int chinese; +}; + +void print_s(const void *record) +{ + const struct score_st *r = record; + + printf("%d %s %d %d\n", r->id, r->name, r->math, r->chinese); +} + +int id_cmp(const void *key, const void *record) +{ + const int *k = key; + const struct score_st *r = record; + + return (*k - r->id); +} + +int name_cmp(const void *key, const void *record) +{ + const char *k = key; + const struct score_st *r = record; + + return strcmp(k, r->name); +} + + +int main() +{ + LLIST *handler; + int i, ret; + struct score_st tmp; + + handler = llist_create(sizeof(struct score_st)); + if (NULL == handler) + exit(1); + + for (i = 0; i < 7; i++) + { + tmp.id = i; + snprintf(tmp.name, NAMESIZE, "std%d", i); + tmp.math = rand() % 100; + tmp.chinese = rand() % 100; + + ret = llist_insert(handler, &tmp, LLIST_FORWARD); + if (ret) + exit(1); + } + + llist_travel(handler, print_s); + + printf("\n\n"); + + // int id = 3; + char *del_name = "std6"; + + // ret = llist_delete(handler, &id, id_cmp); + ret = llist_delete(handler, del_name, name_cmp); + if (ret) + printf("llist_deleter failed!\n"); + + llist_travel(handler, print_s); + + + +#if 0 + int id = 3; + struct score_st *data; + + data = llist_find(handler, &id, id_cmp); + if (NULL == data) + printf("Can not find!\n"); + else + print_s(data); + +#endif + + + llist_destroy(handler); + + exit(0); +} \ No newline at end of file diff --git a/Chapter11/ds/line/list/linklist/double/lib3/Makefile b/Chapter11/ds/line/list/linklist/double/lib3/Makefile new file mode 100644 index 0000000..a7681ed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib3/Makefile @@ -0,0 +1,31 @@ +# 方便起见一般都会先定义编译器链接器 +CC = gcc +LD = gcc + +# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c +SRCS = $(wildcard *.c) + +# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o +OBJS = $(patsubst %c, %o, $(SRCS)) + +# 可执行文件的名字 +TARGET = main + +# .PHONE伪目标,具体含义百度一下一大堆介绍 +.PHONY:all clean + +# 要生成的目标文件 +all: $(TARGET) + +# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o +# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 +$(TARGET): $(OBJS) + $(LD) -o $@ $^ + +# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 +%.o:%.c + $(CC) -c $^ + +# make clean删除所有.o和目标文件 +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Chapter11/ds/line/list/linklist/double/lib3/llist.c b/Chapter11/ds/line/list/linklist/double/lib3/llist.c new file mode 100644 index 0000000..d7b087d --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib3/llist.c @@ -0,0 +1,142 @@ +#include +#include +#include + +#include "llist.h" + +int llist_insert(LLIST *ptr, const void *data, int mode); +void *llist_find(LLIST *ptr, const void *key, llist_cmp *); +int llist_delete(LLIST *, const void *key, llist_cmp *); +int llist_fetch(LLIST *, const void *key, llist_cmp *, void *data); +void llist_travel(LLIST *ptr, llist_op *op); + +LLIST *llist_create(int initsize) +{ + LLIST *new; + + new = malloc(sizeof(*new)); // !!! 不是sizeof(initsize),也不是new,是*new + if (NULL == new) + return NULL; + + new->size = initsize; + new->head.prev = &new->head; + new->head.next = &new->head; + + new->insert = llist_insert; + new->delete = llist_delete; + new->find = llist_find; + new->fetch = llist_fetch; + new->travel = llist_travel; + + return new; +} + +int llist_insert(LLIST *ptr, const void *data, int mode) +{ + struct llist_node_st *newnode; + + newnode = malloc(sizeof(*newnode) + ptr->size); // -4 + if (NULL == newnode) + return -1; + + memcpy(newnode->data, data, ptr->size); + + if (LLIST_FORWARD == mode) + { + newnode->prev = &ptr->head; + newnode->next = ptr->head.next; + } + else if (LLIST_BACKWARD == mode) + { + newnode->prev = ptr->head.prev; + newnode->next = &ptr->head; + } + else // error + { + return -3; + } + + // !!! 妙啊 + newnode->next->prev = newnode; + newnode->prev->next = newnode; + + return 0; +} + +static struct llist_node_st *find_(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + { + if (0 == cmp(key, cur->data)) + break; + } + + return cur; // 找不到的时候,返回的cur就是ptr,返回NULL +} + +void *llist_find(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *node; + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return NULL; + + return node->data; +} + +int llist_delete(LLIST *ptr, const void *key, llist_cmp *cmp) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + // !!! + node->prev->next = node->next; + node->next->prev = node->prev; + free(node); + return 0; +} + +int llist_fetch(LLIST *ptr, const void *key, llist_cmp *cmp, void *data) +{ + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + node->next->prev = node->prev; + node->prev->next = node->next; + + if (data != NULL) + memcpy(data, node->data, ptr->size); + + free(node); + + return 0; +} + +void llist_travel(LLIST *ptr, llist_op *op) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + op(cur->data); +} + +void llist_destroy(LLIST *ptr) +{ + struct llist_node_st *cur, *next; + + for (cur = ptr->head.next; cur != &ptr->head; cur = next) + { + next = cur->next; + free(cur); + } + + free(ptr); +} diff --git a/Chapter11/ds/line/list/linklist/double/lib3/llist.h b/Chapter11/ds/line/list/linklist/double/lib3/llist.h new file mode 100644 index 0000000..2abdfb4 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib3/llist.h @@ -0,0 +1,38 @@ +#ifndef LLIST_H__ +#define LLIST_H__ + +#define LLIST_FORWARD 1 +#define LLIST_BACKWARD 2 + +typedef void llist_op(const void *); +typedef int llist_cmp(const void *, const void *); + +// !!! 变长结构体 +struct llist_node_st +{ + struct llist_node_st *prev; + struct llist_node_st *next; + // data要放在最后 + char data[1]; // 占位符,数据的起始。C99才只是[0] +}; + +typedef struct llist_head +{ + int size; + struct llist_node_st head; + + int (*insert)(struct llist_head *, const void *, int); + void *(*find)(struct llist_head *, const void *, llist_cmp *); + int (*delete)(struct llist_head *, const void *, llist_cmp *); + int (*fetch)(struct llist_head *, const void *, llist_cmp *, void *); + void (*travel)(struct llist_head *, llist_op *); + +} LLIST; + + + +LLIST *llist_create(int initsize); + +void llist_destroy(LLIST *ptr); + +#endif diff --git a/Chapter11/ds/line/list/linklist/double/lib3/main.c b/Chapter11/ds/line/list/linklist/double/lib3/main.c new file mode 100644 index 0000000..028341c --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib3/main.c @@ -0,0 +1,97 @@ +#include +#include +#include + +#include "llist.h" + +#define NAMESIZE 32 + +struct score_st +{ + int id; + char name[NAMESIZE]; + int math; + int chinese; +}; + +void print_s(const void *record) +{ + const struct score_st *r = record; + + printf("%d %s %d %d\n", r->id, r->name, r->math, r->chinese); +} + +int id_cmp(const void *key, const void *record) +{ + const int *k = key; + const struct score_st *r = record; + + return (*k - r->id); +} + +int name_cmp(const void *key, const void *record) +{ + const char *k = key; + const struct score_st *r = record; + + return strcmp(k, r->name); +} + + +int main() +{ + LLIST *handler; + int i, ret; + struct score_st tmp; + + handler = llist_create(sizeof(struct score_st)); + if (NULL == handler) + exit(1); + + for (i = 0; i < 7; i++) + { + tmp.id = i; + snprintf(tmp.name, NAMESIZE, "std%d", i); + tmp.math = rand() % 100; + tmp.chinese = rand() % 100; + + ret = handler->insert(handler, &tmp, LLIST_FORWARD); + if (ret) + exit(1); + } + + handler->travel(handler, print_s); + + + +#if 0 + printf("\n\n"); + + // int id = 3; + char *del_name = "std6"; + + // ret = llist_delete(handler, &id, id_cmp); + ret = llist_delete(handler, del_name, name_cmp); + if (ret) + printf("llist_deleter failed!\n"); + + llist_travel(handler, print_s); + + + + int id = 3; + struct score_st *data; + + data = llist_find(handler, &id, id_cmp); + if (NULL == data) + printf("Can not find!\n"); + else + print_s(data); + +#endif + + + llist_destroy(handler); + + exit(0); +} \ No newline at end of file diff --git a/Chapter11/ds/line/list/linklist/double/lib4/Makefile b/Chapter11/ds/line/list/linklist/double/lib4/Makefile new file mode 100644 index 0000000..a7681ed --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib4/Makefile @@ -0,0 +1,31 @@ +# 方便起见一般都会先定义编译器链接器 +CC = gcc +LD = gcc + +# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c +SRCS = $(wildcard *.c) + +# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o +OBJS = $(patsubst %c, %o, $(SRCS)) + +# 可执行文件的名字 +TARGET = main + +# .PHONE伪目标,具体含义百度一下一大堆介绍 +.PHONY:all clean + +# 要生成的目标文件 +all: $(TARGET) + +# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o +# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件 +$(TARGET): $(OBJS) + $(LD) -o $@ $^ + +# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成 +%.o:%.c + $(CC) -c $^ + +# make clean删除所有.o和目标文件 +clean: + rm -f $(OBJS) $(TARGET) diff --git a/Chapter11/ds/line/list/linklist/double/lib4/llist.c b/Chapter11/ds/line/list/linklist/double/lib4/llist.c new file mode 100644 index 0000000..014853c --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib4/llist.c @@ -0,0 +1,153 @@ +#include +#include +#include + +#include "llist.h" + +// !!! 变长结构体 +struct llist_node_st +{ + struct llist_node_st *prev; + struct llist_node_st *next; + // data要放在最后 + char data[1]; // 占位符,数据的起始。C99才只是[0] +}; + +struct llist_head_st +{ + int size; + struct llist_node_st head; +}; + +LLIST *llist_create(int initsize) +{ + struct llist_head_st *new; + + new = malloc(sizeof(*new)); // !!! 不是sizeof(initsize),也不是new,是*new + if (NULL == new) + return NULL; + + new->size = initsize; + new->head.prev = &new->head; + new->head.next = &new->head; + + return new; +} + +int llist_insert(LLIST *p, const void *data, int mode) +{ + struct llist_node_st *newnode; + struct llist_head_st *ptr = p; + + newnode = malloc(sizeof(*newnode) + ptr->size); // -4 + if (NULL == newnode) + return -1; + + memcpy(newnode->data, data, ptr->size); + + if (LLIST_FORWARD == mode) + { + newnode->prev = &ptr->head; + newnode->next = ptr->head.next; + } + else if (LLIST_BACKWARD == mode) + { + newnode->prev = ptr->head.prev; + newnode->next = &ptr->head; + } + else // error + { + return -3; + } + + // !!! 妙啊 + newnode->next->prev = newnode; + newnode->prev->next = newnode; + + return 0; +} + +static struct llist_node_st *find_(struct llist_head_st *ptr, + const void *key, + llist_cmp *cmp) +{ + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + { + if (0 == cmp(key, cur->data)) + break; + } + + return cur; // 找不到的时候,返回的cur就是ptr,返回NULL +} + +void *llist_find(LLIST *p, const void *key, llist_cmp *cmp) +{ + struct llist_head_st *ptr = p; + struct llist_node_st *node; + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return NULL; + + return node->data; +} + +int llist_delete(LLIST *p, const void *key, llist_cmp *cmp) +{ + struct llist_head_st *ptr = p; + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + // !!! + node->prev->next = node->next; + node->next->prev = node->prev; + free(node); + return 0; +} + +int llist_fetch(LLIST *p, const void *key, llist_cmp *cmp, void *data) +{ + struct llist_head_st *ptr = p; + struct llist_node_st *node; + + node = find_(ptr, key, cmp); + if (node == &ptr->head) + return -1; + + node->next->prev = node->prev; + node->prev->next = node->next; + + if (data != NULL) + memcpy(data, node->data, ptr->size); + + free(node); + + return 0; +} + +void llist_travel(LLIST *p, llist_op *op) +{ + struct llist_head_st *ptr = p; + struct llist_node_st *cur; + + for (cur = ptr->head.next; cur != &ptr->head; cur = cur->next) + op(cur->data); +} + +void llist_destroy(LLIST *p) +{ + struct llist_head_st *ptr = p; + struct llist_node_st *cur, *next; + + for (cur = ptr->head.next; cur != &ptr->head; cur = next) + { + next = cur->next; + free(cur); + } + + free(ptr); +} diff --git a/Chapter11/ds/line/list/linklist/double/lib4/llist.h b/Chapter11/ds/line/list/linklist/double/lib4/llist.h new file mode 100644 index 0000000..f000d31 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib4/llist.h @@ -0,0 +1,27 @@ +#ifndef LLIST_H__ +#define LLIST_H__ + +#define LLIST_FORWARD 1 +#define LLIST_BACKWARD 2 + +// !!! 实现了隐藏 LLIST 的实现方法 +typedef void LLIST; + +typedef void llist_op(const void *); +typedef int llist_cmp(const void *, const void *); + +LLIST *llist_create(int initsize); + +int llist_insert(LLIST *, const void *data, int mode); + +void *llist_find(LLIST *, const void *key, llist_cmp *); + +int llist_delete(LLIST *, const void *key, llist_cmp *); + +int llist_fetch(LLIST *, const void *key, llist_cmp *, void *data); + +void llist_travel(LLIST *, llist_op *); + +void llist_destroy(LLIST *); + +#endif diff --git a/Chapter11/ds/line/list/linklist/double/lib4/main.c b/Chapter11/ds/line/list/linklist/double/lib4/main.c new file mode 100644 index 0000000..e736037 --- /dev/null +++ b/Chapter11/ds/line/list/linklist/double/lib4/main.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "llist.h" + +#define NAMESIZE 32 + +struct score_st +{ + int id; + char name[NAMESIZE]; + int math; + int chinese; +}; + +void print_s(const void *record) +{ + const struct score_st *r = record; + + printf("%d %s %d %d\n", r->id, r->name, r->math, r->chinese); +} + +int id_cmp(const void *key, const void *record) +{ + const int *k = key; + const struct score_st *r = record; + + return (*k - r->id); +} + +int name_cmp(const void *key, const void *record) +{ + const char *k = key; + const struct score_st *r = record; + + return strcmp(k, r->name); +} + + +int main() +{ + LLIST *handler; + int i, ret; + struct score_st tmp; + + handler = llist_create(sizeof(struct score_st)); + if (NULL == handler) + exit(1); + + for (i = 0; i < 7; i++) + { + tmp.id = i; + snprintf(tmp.name, NAMESIZE, "std%d", i); + tmp.math = rand() % 100; + tmp.chinese = rand() % 100; + + ret = llist_insert(handler, &tmp, LLIST_FORWARD); + if (ret) + exit(1); + } + + llist_travel(handler, print_s); + + printf("\n\n"); + + // int id = 3; + char *del_name = "std6"; + + // ret = llist_delete(handler, &id, id_cmp); + ret = llist_delete(handler, del_name, name_cmp); + if (ret) + printf("llist_deleter failed!\n"); + + llist_travel(handler, print_s); + + + +#if 0 + int id = 3; + struct score_st *data; + + data = llist_find(handler, &id, id_cmp); + if (NULL == data) + printf("Can not find!\n"); + else + print_s(data); + +#endif + + + llist_destroy(handler); + + exit(0); +} \ No newline at end of file diff --git a/Chapter11/数据结构.md b/Chapter11/数据结构.md index c8a1454..32819fc 100644 --- a/Chapter11/数据结构.md +++ b/Chapter11/数据结构.md @@ -14,12 +14,20 @@ 会更加简单,无头的话,更改首部节点会麻烦。 + 头节点不仅可以作为起点,还可以作为存储信息的仓库,因为头节点只有*next是必须的。 + - 单链表 - 循环 - 不循环 + - 双向链表 + + `lib`四个版本,第一个最基础完善,第二个改成了变长结构体,第三个在第二个的基础上封装了函数指针,第四个在第二个的基础上隐藏了数据结构,只暴露接口。 + - 循环 - 不循环 + + 学到这里可以去读一下内核有关**list**的实现,主要都是宏和内联函数。 - 栈