#ifndef _LIST_H_
#define _LIST_H_
typedef struct node{    //节点结构
    void *data;
    struct node *next;
}node;

typedef struct{    //链表结构
    struct node *head;
    struct node *tail;
    long len;
}List;

extern void  list_init(List *list);	
extern int   is_empty(List *list);
extern void  list_insert(List *list, void *data);    		 			//默认采用尾插法
extern void  list_insert_at_head(List *list, void *data);    			//头插法
extern void  list_insert_at_tail(List *list, void *data);    			//尾插法
extern void  list_insert_at_index(List *list, void *data, long idx);	//随插法

extern void *list_delete(List *list, void *key, int (*compare)(const void *, const void *));
extern void *list_search(List *list, void *key, int (*compare)(const void *, const void *));
extern void  list_sort(List *list, int (*compare)(const void *, const void *));
extern void  list_traverse(List *list, void (*handle)(void *));
extern void  list_reverse(List *list);
extern long  list_get_lenth(List *list);
extern void *list_get_element(List *list, int idx);
extern void  list_destroy(List *list, void (*destroy)(void *data));	

#endif

//list.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "list.h"

void list_init(List *list)
{
    list->head = NULL;
    list->tail = NULL;
    list->len = 0;
}

int is_empty(List *list)
{
    return (list->head == NULL);
}

static struct node *make_node(void *data)    //把用户传递过来的数据打包为一个链表节点
{
    struct node *n;

    n = malloc(sizeof(struct node));
    assert(n != NULL);

    n->next = NULL;
    n->data = data;

    return n;
}

void list_insert_at_head(List *list, void *data)    //头插法
{
    struct node *n;
    n = make_node(data);

    if(list->head == NULL)
	{ //如果是空链表
        list->head = n;
        list->tail = n;
    }
    else
	{                   //如果不是非空链表
        n->next = list->head;
        list->head = n;
    }
    list->len++;
}

void list_insert_at_index(List *list, void *data, long index)
{
    long i = 1; //从1开始算
    struct node *p, *n;

    p = list->head;

    while(p && i < index)
	{
        p = p->next;
        i++;
    }

    if(p)
	{ //如果链表遍历完了,计数i还没到index,说明第index个节点不存在。
        n = make_node(data);
        n->next = p->next;
        p->next = n;
        list->len++;
    }
}

void list_insert_at_tail(List *list, void *data)    //尾插法
{
    struct node *n;
    n = make_node(data);

    if(is_empty(list))
	{    //如果是空链表
        list->head = n;
        list->tail = n;
    }
    else
	{                      //如果不是非空链表
        list->tail->next = n;
        list->tail = n;
    }
    list->len++;
}
/*
void list_insert(List *list, void *data)    //默认采用尾插法
{
#if 0
    list_insert_at_tail(list, data);
#else
    struct node *n;

    n = make_node(data);

    if(list->head == NULL){
        list->head = n;
        list->tail = n;
    } else {
        list->tail->next = n;
        list->tail = n;
    }
    list->len++;
#endif
}
*/

void list_insert(List *list, void *data)
{
    struct node *n;

    n = make_node(data);

    if(list->head == NULL)
	{
        list->head = n;
        list->tail = n;
    } 
	else 
	{
        list->tail->next = n;
        list->tail = n;
    }
    list->len++;
}

void * list_delete(List *list, void *key, int (*compare)(const void *, const void *))
{
    void *data;
    struct node *n, *t;
    n = list->head;

    if(!compare(n->data, key))
	{    //如果要删除的节点为首节点
        t = n;
        data = n->data;
        list->head = n->next;
        free(t);
        list->len--;
        return data;
    }

    while(n->next != NULL)
	{        //遍历查找符合条件的节点,删除之
        if(compare(n->next->data, key) == 0)
		{    //只删除第一个符合条件的节点。
            t = n->next;
            if(n->next == list->tail)
			{
                list->tail = n;
            }
            n->next = n->next->next;
            data = t->data;
            free(t);
            list->len--;
            return data;    //把删除的数据返回给用户,供用户后续的处理使用。
        }
        n = n->next;
    }
    return NULL;    //没找到匹配的节点,返回NULL
}

void *list_search(List *list, void *key, int (*compare)(const void *, const void *))
{
    struct node *n;
    n = list->head;

    while(n)
	{
        if(!compare(n->data, key))
		{    //找到了,返回找到的数据
            return n->data;
        }
        n = n->next;    
    }

    return NULL;    //找不到,返回NULL
}

static struct node *find_min_node(List *list,
        int (*compare)(const void *, const void *))
{
    struct node *min, *n;

    n = list->head;
    min = list->head;

    while(n)
	{
        if(compare(min->data, n->data) > 0)
		{
            min = n;
        }
        n = n->next;
    }

    return min;
}

static void delete_node(List *list, struct node *key)
{
    struct node *n;

    n = list->head;

    if(n == key)
	{
        list->head = n->next;
        return;
    }

    while(n->next)
	{
        if(n->next == key)
		{
            if(key == list->tail){
                list->tail = n;
            }
            n->next = n->next->next;
            return;
        }
        n = n->next;
    }
}

static void insert_node(List *list, struct node *key)
{
    if(list->head == NULL)
	{
        list->head = key;
        list->tail = key;
    }
	else
	{
        list->tail->next = key;
        list->tail = key;
    }
}

void list_sort(List *list, int (*compare)(const void *, const void *))
{
    List tmp;
    struct node *n;

    list_init(&tmp);

    while(! is_empty(list))
	{
        n = find_min_node(list, compare);
        delete_node(list, n);
        n->next = NULL;
        insert_node(&tmp, n);
    }
    list->head = tmp.head;
    list->tail = tmp.tail;
}

void list_traverse(List *list, void (*handle)(void *))
{
    struct node *p;
    p = list->head;

    while(p)
	{
        handle(p->data);
        p = p->next;
    }
}

void list_reverse(List *list)
{
    struct node *pre = NULL, *next, *p = list->head;

    list->tail = list->head;    //tail指向head;
    while(p)
	{
        next = p->next;
        if(!next)
		{  //当p->next为最后一个节点时,让head指向p->next
            list->head = p;
        }
        //记录当前节点为pre,作为下一个节点的next.第一个节点为NULL,初始化时已定义。
        p->next = pre;
        pre = p;
        p = next;
    }
}

long list_get_lenth(List *list)
{
    return (list->len);
}

void *list_get_element(List *list, int idx)
{
    int i = 1;
    struct node *n;
    n = list->head;

    while(n && i < idx)
	{
        i++;
        n = n->next;
    }

    if(n)
	{
        return n->data;
    }

    return NULL;
}

void list_destroy(List *list, void (*destroy)(void *))
{
    struct node *n, *t;
	list->len = 0;
    n = list->head;

    while(n)
	{
        t = n->next;    //t只起一个记录n->next的功能,否则后面把n free掉之后,就找不到n->next了。
        if(destroy){  //传递用户自定义的数据处理函数,为0时不执行
            destroy(n->data);    //使用用户提供的destroy函数来释放用户传递过来的数据。
        }
        free(n);    
        n = t;  //把n free掉之后,再把t给n,相当于把n->next给n,如此循环遍历链表,挨个删除,
    }
}

//main.c
#include <stdio.h>

#include "list.h"

typedef struct test
{
    int val1;
    float val2;
}test_t;

void handle(void *data)
{
    test_t *test = (test_t *)data;
    printf("val1:%d, val2:%f\n", test->val1, test->val2);
}

int compare_int(const void *s1, const void *s2)
{
    test_t *data1 = (test_t *)s1;
    int *data2 =(int *)s2;

    return (data1->val1 - *data2);
}

int compare_int_sort(const void *s1, const void *s2)
{
    test_t *data1 = (test_t *)s1;
    test_t *data2 = (test_t *)s2;

    return (data1->val1 - data2->val1);
}

void print(List *list)
{
    printf("list len = %ld\n", list_get_lenth(list));
    if(!is_empty(list)){ 
        //test list_reverse
        list_traverse(list, handle);
    }
    else{
        printf("\tthe list is empty\n");
    }
}

int main(void)
{
    List list;
	int key = 20;
	test_t *ret;
   
    test_t test1 = {10, 10.5};
	test_t test2 = {20, 20.5};
	test_t test3 = {30, 30.5};
	test_t test4 = {40, 40.5};
	test_t test5 = {50, 50.5};

	list_init(&list);

    //test list_insert
    printf("------insert(_at_tail)----\n");
    list_insert(&list, &test1);
    list_insert(&list, &test2);
    list_insert(&list, &test3);
    print(&list);

    //test list_delete
    printf("------delete----\n");
    list_delete(&list, &test1.val1, compare_int);
    print(&list);

    //test list_insert_at_head
    printf("------insert_at_head----\n");
    list_insert_at_head(&list, &test4);
    print(&list);

    //test list_insert_at_index
    printf("------insert_at_index(2)----\n");
    list_insert_at_index(&list, &test5, 2);
    print(&list);

    //test list_reverse
    printf("------reverse----\n");
    list_reverse(&list);
    print(&list);

    //test list_search
    printf("------search----\n");
    ret = list_search(&list, &key, compare_int);
    printf("%d:%f\n", ret->val1, ret->val2);
    key = 50;
    ret = list_search(&list, &key, compare_int);
    printf("%d:%f\n", ret->val1, ret->val2);

    //test list_get_element 
    printf("------list_get_element----\n");
    ret = list_get_element(&list, 2);
    printf("%d:%f\n", ret->val1, ret->val2);
    ret = list_get_element(&list, 3);
    printf("%d:%f\n", ret->val1, ret->val2);

    //test list_sort
    printf("-----sort----\n");
    list_sort(&list, compare_int_sort);
    print(&list);

    //test list_destroy
    printf("-----destroy----\n");
    list_destroy(&list, NULL);

    return 0;
}