C语言实现通用链表

软件开发大郭
0 评论
/
7 阅读
/
20599 字
23 2023-11
分类:

需求

相信很多项目中用动态内存来管理数据的时候会有用到链表,这比数组等方式方便多了。

网上收集的一个C语言双向链表,适合嵌入式等环境使用。

代码实现

C语言实现的双向通用链表,代码如下:

/*************************
* File node_link_list.h
**************************/
 
#ifndef _NODE_LINK_LIST_H
#define _NODE_LINK_LIST_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
 
// 节点,外部创建结构体将其挂在data成员上即可
typedef struct link_list_data_node
{
    void * data;
    struct link_list_data_node * next;
}link_list_data_node_t;
 
 
 // 链表
typedef struct node_link_list
{
    link_list_data_node_t * head; // 头部
    link_list_data_node_t * tail; // 尾部
    unsigned int count; // 节点数
    int (*equal)(void * data1, void * data2);
}node_link_list_t;
 
 
//迭代器
typedef struct node_link_list_iterator
{
    link_list_data_node_t * node;
    unsigned int count;
    unsigned int all_size;
} node_link_list_iterator_t;
 
 
//创建链表
node_link_list_t * create_node_link_list();
  
//创建链表,带有相等参数,用于查找
node_link_list_t* create_search_link_list(int(*equal)(void * a, void * b));
 
//释放链表
void destroy_node_link_list(node_link_list_t * list);
 
//释放链表的同时销毁数据节点,主要用于每个节点单独从分配内存后插入链表数据节点的情况
void destroy_node_link_list2(node_link_list_t * list, bool data_release);
 
void destroy_node_link_list3(node_link_list_t * list, bool data_release, void (*data_node_release)(void *data));
 
//插入在头部
void node_link_list_insert_at_head(node_link_list_t * list, void* data);
 
//插入在尾部
void node_link_list_insert_at_tail(node_link_list_t * list, void* data);
 
//指定位置插入
void node_link_list_insert_at_index(node_link_list_t * list, void * data, unsigned int index);
 
//删除头部
void* node_link_list_remove_at_head(node_link_list_t * list);
 
//删除尾部
void* node_link_list_remove_at_tail(node_link_list_t * list);
 
//删除指定位置的节点
void* node_link_list_remove_at_index(node_link_list_t * list, unsigned int index);
 
//获取链表长度
unsigned int node_link_list_get_size(node_link_list_t * list);
 
//打印
void node_link_list_print(node_link_list_t * list, void(*print)(void * data));
  
// 链表判空
int node_link_list_is_empty(node_link_list_t * list);
 
//取得第一个数据
void* node_link_list_get_data_at_head(node_link_list_t * list);
 
//取得最后一个数据
void* node_link_list_get_data_at_tail(node_link_list_t * list);
 
//获取指定位置数据
void* node_link_list_get_data_at_index(node_link_list_t * list, unsigned int index);
 
//获取指定位置数据
void * node_link_list_get_data_at_index2(node_link_list_t * list, unsigned int index);
 
/*
查找某个数据的位置,如果equal方法为空,比较地址,否则调用equal方法
如果不存在返回-1,如果存在,返回出现的第一个位置
*/
int node_link_list_find_data_index(node_link_list_t * list, void * data);
 
//创建迭代器
node_link_list_iterator_t * create_node_link_list_iterator(node_link_list_t * list);
 
//释放迭代器
void destroy_node_link_list_iterator(node_link_list_iterator_t * iterator);
 
//迭代器是否有下一个元素, 0:表示无下一个元素
int node_link_list_iterator_has_next(node_link_list_iterator_t * iterator);
 
//返回迭代器的下一个元素
void* node_link_list_iterator_next(node_link_list_iterator_t * iterator);
 
//删除对象,返回是否删除成功
int node_link_list_remove_data_object(node_link_list_t * list, void * data);
 
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif // _node_link_listH
/*************************
*@File node_link_list.h.c
**************************/
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "node_link_list.h"
 
#define THIS_FILE  "node_link_list.c"
 
 
//创建链表
node_link_list_t * create_node_link_list()
{
    node_link_list_t * list = NULL;
 
    list = (node_link_list_t *)malloc(sizeof(node_link_list_t));
    if (list != NULL)
    {
        list->count = 0;
        list->head = NULL;
        list->tail = NULL;
        list->equal = NULL;
    }
 
    return list;
}
 
 
//创建链表,带有相等参数,用于查找
node_link_list_t * create_search_link_list(int(*equal)(void * a, void * b))
{
    node_link_list_t * list = NULL;
 
    list = create_node_link_list();
    if (list != NULL)
    {
        list->equal = equal;
    }
 
    return list;
}
 
 
//释放链表
void destroy_node_link_list(node_link_list_t * list)
{
    link_list_data_node_t *node = NULL;
 
    if (list != NULL)
    {
        while (list->head != NULL)
        {
            node = list->head->next;
            free(list->head);
            list->head = node;
        }
 
        free(list);
        list = NULL;
    }
}
 
 
//释放链表的同时销毁数据节点,主要用于每个节点单独从分配内存后插入链表数据节点的情况
void destroy_node_link_list2(node_link_list_t * list, bool data_release)
{
    link_list_data_node_t *node = NULL;
    void *data = NULL;
 
    if (list != NULL)
    {
        while (list->head != NULL)
        {
            node = list->head->next;
 
            if (data_release)
            {
                data = (list->head)->data;
                if (data != NULL)
                {
                    free(data);
                    data = NULL;
                }
            }
 
            free(list->head);
            list->head = node;
        }
 
        free(list);
        list = NULL;
    }
}
 
 
void destroy_node_link_list3(node_link_list_t * list, bool data_release, void (*data_node_release)(void *data))
{
    link_list_data_node_t *node = NULL;
    void *data = NULL;
 
    if (list != NULL)
    {
        while (list->head != NULL)
        {
            node = list->head->next;
 
            if (data_release)
            {
                data = (list->head)->data;
                if (data != NULL)
                {
                    if (data_node_release != NULL)
                    {
                        data_node_release(data);
                        data = NULL;
                    }
                }
            }
 
            free(list->head);
            list->head = node;
        }
 
        free(list);
        list = NULL;
    }
}
 
 
int node_link_list_is_empty(node_link_list_t * list)
{
    if (list == NULL)
    {
       return 1;
    }
    else
    {
        return (list->count == 0);
    }
}
 
 
//插入在头部
void node_link_list_insert_at_head(node_link_list_t * list, void * data)
{
    if (list != NULL)
    {
        link_list_data_node_t * node = (link_list_data_node_t *)malloc(sizeof(link_list_data_node_t));
        if (node != NULL)
        {   
            node->data = data;
            node->next = NULL;
        
            if (list->count > 0)
            {
                node->next = list->head;
                list->head = node;
                //printf("[%s:%d]\n", __FUNCTION__, __LINE__);
            }
            else // 第一个节点
            {
                list->head = node;
                list->tail = node;
                //printf("[%s:%d]\n", __FUNCTION__, __LINE__);
            }
 
            (list->count)++;
        }
    }
}
 
 
//插入在尾部
void node_link_list_insert_at_tail(node_link_list_t * list, void * data)
{
    if (list != NULL)
    {
        link_list_data_node_t * node = (link_list_data_node_t *)malloc(sizeof(link_list_data_node_t));
        if (node != NULL)
        {
            node->data = data;
            node->next = NULL;
            if (list->count > 0)
            {
                list->tail->next = node;
                list->tail = node;
            }
            else
            {
                list->head = node;
                list->tail = node;  
            }
 
            (list->count)++;
        }
    }
}
 
 
//指定位置插入
void node_link_list_insert_at_index(node_link_list_t * list, void * data, unsigned int index)
{
    if (list != NULL)
    {
        if (index == 0)
        {
            node_link_list_insert_at_head(list, data);
            return;
        }
 
        if (index == list->count)
        {
            node_link_list_insert_at_tail(list, data);
            return;
        }
 
        link_list_data_node_t * node = (link_list_data_node_t *)malloc(sizeof(link_list_data_node_t));
        if (node != NULL)
        {
            node->data = data;
            node->next = NULL;
        
            link_list_data_node_t *tmp = list->head;
            unsigned int i = 0;
 
            for (i = 0; i < (index - 1); i++)
            {
                tmp = tmp->next;
            }
 
            node->next = tmp->next;
            tmp->next = node;
        
            (list->count)++;
        }
    }
}
 
 
//删除头部
void* node_link_list_remove_at_head(node_link_list_t * list)
{
    void *data = NULL;
 
    if (list != NULL)
    {
        link_list_data_node_t * tmp = list->head;
        if (tmp != NULL)
        {
            list->head = tmp->next;
            data = tmp->data;
            free(tmp);
 
            (list->count)--;
            if (list->count == 0)
            {
                list->tail = NULL;
            }
        }       
    }
 
    return data;
}
 
 
//删除尾部
void * node_link_list_remove_at_tail(node_link_list_t * list)
{
    void * data = NULL;
 
    if (list != NULL)
    {
        if (list->count == 1)
        {
            return node_link_list_remove_at_head(list);
        }
 
        link_list_data_node_t * tmp = list->head;
        if (tmp != NULL)
        {
            while (tmp->next != list->tail)
            {
                tmp = tmp->next;
            }
        }
 
        if (list-> tail != NULL)
        {
            data = list->tail->data;
            free(list->tail);
 
            tmp->next = NULL;
            list->tail = tmp;
 
            (list->count)--;
        }
    }
 
    return data;
}
 
 
 
//删除
void* node_link_list_remove_at_index(node_link_list_t * list, unsigned int index)
{
    void *data = NULL;
 
    if (list != NULL)
    {
        if (index == 0)
        {
            return node_link_list_remove_at_head(list);
        }
 
        if (index == list->count - 1)
        {
            return node_link_list_remove_at_tail(list);
        }
    
        link_list_data_node_t * p = list->head;
        unsigned int i = 0;
 
        for (i = 0; i < (index - 1); i++)
        {
            p = p->next;
        }
 
        link_list_data_node_t * tmp = p->next;
        if (tmp != NULL)
        {
            p->next = p->next->next;
            data = tmp->data;
            free(tmp);
            
            (list->count)--;
        }
    }
 
    return data;
}
 
 
// 获取链表长度
unsigned int node_link_list_get_size(node_link_list_t * list)
{
    if (list != NULL)
    {
        return list->count;
    }
 
    return 0;
}
 
 
//打印
void node_link_list_print(node_link_list_t * list, void(* print)(void * data))
{
    if (list != NULL)
    {
        link_list_data_node_t * node = list->head;
        while (node != NULL)
        {
            if (print != NULL)
            {
                 (*print)(node->data);
            }   
            node = node->next;
        }
    }
}
 
 
//取得第一个数据
void* node_link_list_get_data_at_head(node_link_list_t * list)
{
    if (list != NULL)
    {
        return list->head->data;
    }
 
    return NULL;
}
 
//取得最后一个数据
void* node_link_list_get_data_at_tail(node_link_list_t * list)
{
    if (list != NULL)
    {
        return list->tail->data;
    }
 
    return NULL;
}
 
 
//获取指定位置数据
void * node_link_list_get_data_at_index(node_link_list_t * list, unsigned int index)
{    
    if (list != NULL)
    { 
        if (index == list->count - 1)
        {
            return node_link_list_get_data_at_tail(list);
        }
        else if (index == 0)
        {
            return node_link_list_get_data_at_head(list);
        } 
 
        link_list_data_node_t * node = list->head;
        unsigned int i = 0;
        
        for (i = 0; i < index; i++)
        {
            node = node->next;
        }
 
        if(node != NULL)
        {
            return node->data;
        }
    }
 
    return NULL;
}
 
//获取指定位置数据
void * node_link_list_get_data_at_index2(node_link_list_t * list, unsigned int index)
{    
    if (list != NULL)
    {
        if(list->count <= index)
        {
            return NULL;
        }
 
        link_list_data_node_t * node = list->head;
        unsigned int i = 0;
        
        for (i = 0; i < index; i++)
        {
            node = node->next;
        }
 
        return node->data;
    }
 
    return NULL;
}
 
 
/*
查找某个数据的位置,如果equal方法为空,比较地址,否则调用equal方法
如果不存在返回-1,如果存在,返回出现的第一个位置
*/
int node_link_list_find_data_index(node_link_list_t * list, void * data)
{
    int pos = 0;
 
    if (list != NULL)
    {
        link_list_data_node_t * node = list->head;
        if (list->equal != NULL)
        {
            while (node != NULL)
            {
                if (node->data == data || (*(list->equal))(node->data, data))
                {
                    return pos;
                }
 
                pos++;
                node = node->next;
            }
        }
        else 
        {
            while (node != NULL)
            {
                if (node->data == data)
                {
                    return pos;
                }
                
                pos++;
                node = node->next;
            }
        }
    }
 
    return -1;
}
 
 
//创建迭代器
node_link_list_iterator_t * create_node_link_list_iterator(node_link_list_t * list)
{
    if (list != NULL)
    {
        node_link_list_iterator_t * iter = (node_link_list_iterator_t *)malloc(sizeof(node_link_list_iterator_t));
        if (iter != NULL)
        {
            iter->node = list->head;
            iter->all_size = list->count;
            iter->count = 0;
 
            return iter;
        }
    }
 
    return NULL;
}
 
 
//释放迭代器
void destroy_node_link_list_iterator(node_link_list_iterator_t * iterator)
{
    if (iterator != NULL)
    {
        free(iterator);
    }
}
 
 
 
//迭代器是否有下一个元素,0:表示无下一个元素
int node_link_list_iterator_has_next(node_link_list_iterator_t * iterator)
{
    if (iterator != NULL)
    {
        return (iterator->count < iterator->all_size);
    }
 
    return 0;
}
 
 
//返回迭代器的下一个元素
void* node_link_list_iterator_next(node_link_list_iterator_t * iterator)
{
    void *data = NULL;
    if (iterator != NULL)
    {
        data = iterator->node->data;
        iterator->node = iterator->node->next;
        (iterator->count)++;  
    }
 
    return data;
}
 
 
//删除对象,返回是否删除成功
int node_link_list_remove_data_object(node_link_list_t * list, void * data)
{
    int ret = 0;
 
    if (list != NULL)
    {
        node_link_list_iterator_t * iter = create_node_link_list_iterator(list);
        if (iter != NULL)
        {
             while (node_link_list_iterator_has_next(iter))
            {
                void* tmp = node_link_list_iterator_next(iter);
                if (data == tmp || 
                   (list->equal != NULL && (*(list->equal))(tmp, data)))
                {
                    ret = 1;
                    break;
                }
            }
 
            if (ret != 0)
            {
                node_link_list_remove_at_index(list, (iter->count - 1));
            }
        }
    }
 
    return ret;
}
 
 
#if defined(TEST) && (TEST==1)
typedef struct my_node
{
    int i;
    char c;
}my_node_t;
 
 
void print(void* p)
{
    my_node_t* data = (my_node_t *)p;
    if (data != NULL)
    {
        printf("data[%d]=%c ", data->i, data->c);
    }
}
 
 
int main(int argc, char *argv[])
{
    const int count =10;
 
    //创建并初始化数据
    my_node_t * data= (my_node_t *)malloc(sizeof(my_node_t) * count);
    if (data == NULL)
    {
        return 0;
    }
 
    //创建链表
    node_link_list_t * list= create_node_link_list();
    if (list == NULL)
    {
        goto END;
    }
 
    int i = 0;
    for (i = 0; i < count; i++)
    {
        data[i].i=i;
        data[i].c=(char)('A'+ i);
        node_link_list_insert_at_tail(list, &data[i]);
    }
    
    node_link_list_print(list, print);
    printf("\n");
 
    //测试三种插入方法
    node_link_list_insert_at_head(list, &data[0]); // 'A'
    node_link_list_insert_at_index(list, &data[1], 1); // 'B'
     node_link_list_insert_at_tail(list, &data[2]); // 'C'
 
    node_link_list_print(list, print);
    printf("\n");
 
    //测试查找
    int index = node_link_list_find_data_index(list, &data[2]);
    printf("index = %d\n", index);
    index = node_link_list_find_data_index(list, &data[4]);
    printf("index = %d\n", index);
  
    //测试使用迭代器输出
    node_link_list_iterator_t * iter = create_node_link_list_iterator(list);
    while(node_link_list_iterator_has_next(iter))
    {
        my_node_t * pp = (my_node_t *)node_link_list_iterator_next(iter);
        if (pp != NULL)
        {
            printf("data[%d]=%c ", pp->i, pp->c);
        }
    }
 
    printf("\n");
 
    node_link_list_remove_at_index(list, 0);
    node_link_list_remove_at_index(list, 1);
    node_link_list_print(list, print);
    printf("\n");
 
END:
    //释放迭代器
    destroy_node_link_list_iterator(iter);
 
    //释放链表
    destroy_node_link_list(list);
 
    //释放数据
    if (data != NULL)
    {
        free(data);
        data = NULL;
    }
 
    return 0;
}
#endif

在代码的头文件中定义一个测试宏,就能启用测试模式

#define TEST 1

如何使用

引入头文件

#include "node_link_list.h"

创建数据节点

//定义节点
typedef struct my_node
{
    int i;
    char c;
}my_node_t;

创建链表

//创建并初始化数据
    my_node_t * data= (my_node_t *)malloc(sizeof(my_node_t) * count);
    if (data == NULL)
    {
        return 0;
    }
 
    //创建链表
    node_link_list_t * list= create_node_link_list();
    if (list == NULL)
    {
        goto END;
    }

完整代码

#include "node_link_list.h"
#include "stdio.h"
//定义节点
typedef struct my_node
{
    int i;
    char c;
}my_node_t;
 
//打印代码
void print(void* p)
{
    my_node_t* data = (my_node_t *)p;
    if (data != NULL)
    {
        printf("data[%d]=%c ", data->i, data->c);
    }
}
 
//主函数
int main(int argc, char *argv[])
{
    const int count =10;
 
    //创建并初始化数据
    my_node_t * data= (my_node_t *)malloc(sizeof(my_node_t) * count);
    if (data == NULL)
    {
        return 0;
    }
 
    //创建链表
    node_link_list_t * list= create_node_link_list();
    if (list == NULL)
    {
        goto END;
    }
 
    int i = 0;
    for (i = 0; i < count; i++)
    {
        data[i].i=i;
        data[i].c=(char)('A'+ i);
        node_link_list_insert_at_tail(list, &data[i]);
    }
    
    node_link_list_print(list, print);
    printf("\n");
 
    //测试三种插入方法
    node_link_list_insert_at_head(list, &data[0]); // 'A'
    node_link_list_insert_at_index(list, &data[1], 1); // 'B'
     node_link_list_insert_at_tail(list, &data[2]); // 'C'
 
    node_link_list_print(list, print);
    printf("\n");
 
    //测试查找
    int index = node_link_list_find_data_index(list, &data[2]);
    printf("index = %d\n", index);
    index = node_link_list_find_data_index(list, &data[4]);
    printf("index = %d\n", index);
  
    //测试使用迭代器输出
    node_link_list_iterator_t * iter = create_node_link_list_iterator(list);
    while(node_link_list_iterator_has_next(iter))
    {
        my_node_t * pp = (my_node_t *)node_link_list_iterator_next(iter);
        if (pp != NULL)
        {
            printf("data[%d]=%c ", pp->i, pp->c);
        }
    }
 
    printf("\n");
 
    node_link_list_remove_at_index(list, 0);
    node_link_list_remove_at_index(list, 1);
    node_link_list_print(list, print);
    printf("\n");
 
END:
    //释放迭代器
    destroy_node_link_list_iterator(iter);
 
    //释放链表
    destroy_node_link_list(list);
 
    //释放数据
    if (data != NULL)
    {
        free(data);
        data = NULL;
    }
 
    return 0;
}
标签:
    暂无数据