通用链表操作接口函数

26 篇文章 6 订阅
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;
}
/*是否为空链表*/
bool 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++;
}
/*从链表的中部index节点插入节点*/
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 *))
{
    list->len = 0;
    struct node *n, *t;
    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,如此循环遍历链表,挨个删除,
    }
}
<span style="font-family: Arial, Helvetica, sans-serif;">main.c</span>
#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 list;
//初始化链表
    list_init(&list);
//测试数据test_t定义
    test_t test1 = {10, 10.5};
<span style="white-space:pre">	</span>test_t test2 = {20, 20.5};
<span style="white-space:pre">	</span>test_t test3 = {30, 30.5};
<span style="white-space:pre">	</span>test_t test4 = {40, 40.5};
<span style="white-space:pre">	</span>test_t test5 = {50, 50.5};
//默认从尾部插入tail
    //test list_insert
    printf("------insert(_at_tail)----\n");
    list_insert(&list, &test1);//10 10.5
    list_insert(&list, &test2);//20 20.5
    list_insert(&list, &test3);//30 30.5 
    print(&list);
//删除
    //test list_delete
    printf("------delete----\n");
    list_delete(&list, &test1.val1, compare_int);//函数指针compare_init
    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
    int key = 20;
    test_t *ret;
    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);
<span style="white-space:pre">	</span>//test if list is empty\n
<span style="white-space:pre">	</span>printf("-----check is_empty------");
<span style="white-space:pre">	</span>if(!is_empty(&list))
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>printf("list is not empty\n");
<span style="white-space:pre">		</span>printf("list len = %ld\n", list_get_lenth(&list));
<span style="white-space:pre">	</span>}
    //test list_destroy
    printf("-----destroy----\n");
    list_destroy(&list, NULL);
<span style="white-space:pre">	</span>//test is_empty
<span style="white-space:pre">	</span>printf("-----is_empty------");
<span style="white-space:pre">	</span>if(!is_empty(&list))
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>printf("list is not empty\n");
<span style="white-space:pre">		</span>printf("list len = %ld\n", list_get_lenth(&list));
<span style="white-space:pre">	</span>}


    return 0;
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值