单链表自动生成函数

本文介绍了一种使用C语言实现的单链表操作方法,包括插入、删除和查找功能,并通过宏定义实现了参数匹配的通用性。此外,还提供了一个完整的示例程序,演示了如何创建、插入、查找及删除链表元素。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
typedef struct SLHead_struct { //single list head
    char * sl_mbr_ptr;//
    unsigned int total_elements;
} SLHeadType;
//入参自动生成宏
#define __STD_PARAM1(t1)      (tmp->t1==the_ele->t1)
#define __STD_PARAM2(t2, ...) (tmp->t2==the_ele->t2)&&__STD_PARAM1(__VA_ARGS__)
#define __STD_PARAM3(t3, ...) (tmp->t3==the_ele->t3)&&__STD_PARAM2(__VA_ARGS__)
#define __STD_PARAM4(t4, ...) (tmp->t4==the_ele->t4)&&__STD_PARAM3(__VA_ARGS__)
#define __STD_PARAM5(t5, ...) (tmp->t5==the_ele->t5)&&__STD_PARAM4(__VA_ARGS__)
#define __STD_PARAM6(t6, ...) (tmp->t6==the_ele->t6)&&__STD_PARAM5(__VA_ARGS__)
//单链表插入函数自动生成宏
#define DEFINE_SINGLE_LIST_INSERT_FUN(the_func_name, node_type, x,...)    \
int the_func_name(SLHeadType * _list_head, node_type * the_ele)           \
{                                                                         \
    node_type * new_ele_ptr  = (node_type *)malloc(sizeof(node_type));    \
    if(new_ele_ptr) {                                                     \
        *new_ele_ptr = *the_ele;                                          \
        new_ele_ptr->next = (node_type *)_list_head->sl_mbr_ptr;          \
        _list_head->sl_mbr_ptr = (char *)new_ele_ptr;                     \
        _list_head->total_elements++;                                     \
        return 0;                                                         \
    }                                                                     \
    return -4;                                                            \
}
//单链表删除函数自动生成宏
#define DEFINE_SINGLE_LIST_DELETE_FUN(the_func_name, node_type, x,...)        \
int the_func_name(SLHeadType * _list_head, node_type * the_ele)               \
{                                                                             \
    node_type * tmp  = (node_type *)_list_head->sl_mbr_ptr;                    \
    node_type ** prv = (node_type **)&_list_head->sl_mbr_ptr;                 \
    while(tmp) {                                                              \
        if(__STD_PARAM##x(__VA_ARGS__)) {                                     \
            *prv = tmp->next;                                                  \
            free((char *)tmp);                                       \
            _list_head->total_elements--;                                     \
            return 0;                                                         \
        }                                                                     \
        prv = &tmp->next;                                                      \
        tmp = tmp->next;                                                       \
    }                                                                         \
    return -7;                                                                \
}
//单链表查找函数自动生成宏
#define DEFINE_SINGLE_LIST_LOOKUP_FUN(the_func_name, node_type, x,...)        \
node_type * the_func_name(SLHeadType * _list_head, node_type * the_ele)       \
{                                                                             \
    node_type * tmp = (node_type *)_list_head->sl_mbr_ptr;                    \
    while(tmp) {                                                              \
        if(__STD_PARAM##x(__VA_ARGS__)) {                                     \
            return tmp;                                                       \
        }                                                                     \
        tmp = tmp->next;                                                      \
    }                                                                         \
    return NULL;                                                              \
}

typedef struct SingleListMbrStruct {
    struct SingleListMbrStruct * next;
    int ip;
    int mask;
    int vpnid;
    int data;
} SingleListMbrType;
//定义查找函数
DEFINE_SINGLE_LIST_INSERT_FUN(single_list_insert_fun, SingleListMbrType, 2,ip,mask);
DEFINE_SINGLE_LIST_DELETE_FUN(single_list_delete_fun, SingleListMbrType, 2,ip,mask);
DEFINE_SINGLE_LIST_LOOKUP_FUN(single_list_lookup_fun, SingleListMbrType, 2,ip,mask);

typedef struct SingleListTestStruct {
    SLHeadType user;
} SingleListTestType;

#define LIST_TOL_NUM  10
show_list_all(SingleListTestType * slt){
    //打印当前链表里的总数,并遍历每个成员
    printf("\n ********print all member start***** \n");
    SingleListMbrType  * tmp_ptr = NULL;
    printf("total num =%d \n",slt->user.total_elements);
    tmp_ptr = (SingleListMbrType  *)slt->user.sl_mbr_ptr;
    while(tmp_ptr){
        printf("ip=%d,mask=%d data=%d \n",tmp_ptr->ip,tmp_ptr->mask,tmp_ptr->data);
        tmp_ptr = tmp_ptr->next;
    }
    printf(" ********print all member end***** \n");
}
int main(){
    int i = 0;
    int rv = 0;
    SingleListTestType  slt = {{0}};
    SingleListMbrType   slt_mbr ={0};
    SingleListMbrType  * tmp_ptr = NULL;
    //插入n个元素,
    for(i = 0; i < LIST_TOL_NUM ;i++){
        slt_mbr.ip = i;
        slt_mbr.mask = i+10;
        slt_mbr.data = 2*i;
        rv = single_list_insert_fun(&slt.user,&slt_mbr);
    }
    printf("遍历一下刚刚插入的数据 \n");
    show_list_all(&slt);

    printf("\n测试查找函数,对应数据链表中存在,执行结果: \n");
    slt_mbr.ip = 3;
    slt_mbr.mask = 13;
    tmp_ptr = single_list_lookup_fun(&slt.user, &slt_mbr);
    if(tmp_ptr){
        printf("查找到对应数据:ip=%d,mask=%d data=%d \n",tmp_ptr->ip,tmp_ptr->mask,tmp_ptr->data);
    }else{
        printf("not found \n");
    }

    printf("\n测试查找函数,对应数据链表中不存在 执行结果:\n");
    slt_mbr.ip = 3;
    slt_mbr.mask = 13;
    tmp_ptr = single_list_lookup_fun(&slt.user, &slt_mbr);
    if(tmp_ptr){
        printf("查找到对应数据:ip=%d,mask=%d data=%d \n",tmp_ptr->ip,tmp_ptr->mask,tmp_ptr->data);
    }else{
        printf("not found \n");
    }

    printf("\n测试要删除的数据是头节点 执行结果:\n");
    slt_mbr.ip = 9;
    slt_mbr.mask = 19;
    rv = single_list_delete_fun(&slt.user, &slt_mbr);
    printf("删除结果 rv = %d \n",rv);
    printf("删除后当前链表的情况");
    show_list_all(&slt);

    printf("\n测试要删除的数据是中间节点 执行结果:\n");
    slt_mbr.ip = 5;
    slt_mbr.mask = 15;
    rv = single_list_delete_fun(&slt.user, &slt_mbr);
    printf("删除结果 rv = %d \n",rv);
    printf("删除后当前链表的情况");
    show_list_all(&slt);

    printf("\n测试要删除的数据不存在 执行结果:\n");
    slt_mbr.ip = 4;
    slt_mbr.mask = 15;
    rv = single_list_delete_fun(&slt.user, &slt_mbr);
    printf("删除结果 rv = %d \n",rv);
    printf("删除后当前链表的情况");
    show_list_all(&slt);
    return 0;
}




<think>根据用户需求,用户希望了解支持可利用空间表的单链表定义及函数重载的C语言实现。注意:C语言本身不支持函数重载(这是C++的特性),但我们可以通过其他方式模拟(如使用不同的函数名或使用泛型技术)。这里我们实现一个支持可利用空间表的单链表(即使用空闲链表来管理删除的节点,以便后续分配时重用)。同时,为了模拟函数重载,我们将为不同类型的数据(int,float,char*)实现类似功能的链表操作,通过使用void*和函数指针来实现通用性,并分别提供不同的操作函数(但函数名不同)来模拟重载。计划实现以下内容:1.定义链表节点结构,包含指向数据的指针(void*)和next指针。2.实现一个全局的空闲链表(可利用空间表),用于回收删除的节点,并在需要分配新节点时优先从空闲链表中获取。3.实现基本的链表操作:创建节点、插入、删除、打印等,同时支持从空闲链表获取节点和将删除的节点放入空闲链表。4.为int,float,char*类型分别提供打印函数和比较函数(用于查找等操作),通过函数指针实现通用操作。注意:由于C语言没有函数重载,我们通过为不同类型定义不同的函数名来区分(如insert_int,insert_float等),或者通过一个统一的函数配合类型标识符来区分类型,但这并不是真正的重载。另一种方法是使用宏来生成类型特化的函数,但这里为了清晰,我们将分别实现几种类型的链表操作。然而,用户要求“函数重载”,这在C语言中无法直接实现,所以我们用以下两种方式之一:a)使用不同的函数名(例如,针对int类型,函数命名为list_insert_int等)b)使用一个通用函数,通过额外的类型参数来区分,内部根据类型调用不同的辅助函数。这里我们采用方式a),因为更清晰,且符合C语言的习惯。但是,用户还要求“可利用空间表”,所以我们实现一个空闲链表(free_list)来管理被释放的节点。步骤:1.定义链表节点和空闲链表头指针。2.实现从空闲链表获取节点(当空闲链表不为空时,从其中取一个节点;否则用malloc分配新节点)3.当删除节点时,不直接free,而是将其放入空闲链表(注意:放入时,需要释放节点中的数据吗?这里我们统一不释放数据,因为数据的内存由用户管理。但是,当链表被销毁时,需要释放所有节点和数据?这取决于设计。为了简单,我们在示例中只管理节点,不管理数据。考虑:当我们将节点放入空闲链表时,节点中的数据指针仍然指向原来的数据,这可能会造成内存泄漏(如果该数据需要被释放的话)。因此,我们设计一个回调函数,由用户在删除节点时决定如何释放数据内存。但是,在放入空闲链表时,我们希望节点是“空白”的,即不包含数据。所以,我们要求用户在将节点放入空闲链表之前,必须自行处理数据(或由链表操作函数处理)。这样设计比较复杂。另一种做法:空闲链表中的节点只保留节点结构,数据指针在节点从空闲链表分配出去后再赋值。因此,当节点被删除并放入空闲链表时,我们将其数据指针置为NULL,这样就不会有悬挂指针。同时,我们约定,当用户删除节点时,如果数据需要释放,则用户需要自己释放数据内存(或者提供释放函数)。为了简化,我们假设节点中的数据由链表外部管理,链表只负责节点结构的复用。这样,删除节点并放入空闲链表时,我们不释放数据,只是将数据指针保留(但这样可能会造成数据内存泄漏,因为后续如果没有外部指针指向该数据,就丢失了)。所以,我们要求用户在使用链表删除操作时,如果数据需要释放,应该在删除之前先释放数据。综合考虑,我们这样设计:-链表节点结构:包含void*data和指向下一节点的指针。-全局空闲链表:是一个单链表,头指针为free_list。-提供函数:get_node(),用于从空闲链表获取一个节点(如果空闲链表不为空,则取一个节点并返回,同时将其从空闲链表移除;如果为空,则malloc新节点)。-提供函数:free_node(),用于将节点放入空闲链表(注意:这里只是回收节点结构,不处理数据)。注意:这样实现,空闲链表中的节点数据指针是未定义的(可能是任意值),所以在分配节点后,需要重新设置数据指针。另外,我们还需要提供销毁整个空闲链表的函数(释放所有节点,因为节点结构也是动态分配的)。下面,我们将实现一个通用链表(不特指某种类型),并分别针对int、float和字符串(char*)提供插入、删除等操作的示例。由于时间有限,我们只实现插入和打印操作,并展示如何使用空闲链表。代码结构:1.定义节点结构体。2.全局空闲链表头指针。3.函数:获取一个节点(优先从空闲链表中取)。4.函数:释放一个节点(将其加入空闲链表)。5.函数:创建链表(头节点,头节点不放入空闲链表机制,因为我们的链表带头节点)。6.针对不同类型数据插入链表的函数函数名不同)和打印函数函数名不同)。7.销毁整个链表(包括头节点,但注意:头节点不放回空闲链表,而是直接free)和销毁空闲链表。注意:头节点与普通节点一样,但我们规定头节点不存储数据,且不在空闲链表中管理。链表为空时,头节点next为NULL。具体实现如下:</think> # 支持可利用空间表的单链表实现 在C语言中实现支持可利用空间表的单链表是一种高效管理内存的策略,通过回收已删除的节点,减少频繁的内存分配与释放操作。以下是完整的C语言实现,包含函数重载机制的模拟: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 单链表节点结构(可存储任意类型数据) typedef struct ListNode { void *data; // 通用数据指针 int dataType; // 数据类型标识 struct ListNode *next; // 指向下一个节点 } ListNode; // 数据类型枚举 typedef enum { INT_TYPE, FLOAT_TYPE, STRING_TYPE } DataType; // 空闲链表(可利用空间表) static ListNode *freeList = NULL; // 创建新节点(优先使用空闲链表中的节点) ListNode *createNode(void *data, DataType dataType) { ListNode *newNode; // 优先从空闲链表中获取节点 if (freeList != NULL) { newNode = freeList; freeList = freeList->next; // 重用节点内存 newNode->data = data; newNode->dataType = dataType; newNode->next = NULL; } // 空闲链表为空则分配新内存 else { newNode = (ListNode *)malloc(sizeof(ListNode)); if (!newNode) { perror("Memory allocation failed"); exit(EXIT_FAILURE); } newNode->data = data; newNode->dataType = dataType; newNode->next = NULL; } return newNode; } // 释放节点(放入空闲链表) void freeNode(ListNode *node) { if (!node) return; // 释放数据内存 if (node->data) { switch (node->dataType) { case STRING_TYPE: free(*(char **)node->data); break; default: // 基本类型无需特殊释放 break; } free(node->data); } // 将节点加入空闲链表 node->next = freeList; freeList = node; } // 在链表尾部添加节点(函数重载机制模拟) ListNode *appendNode(ListNode *head, void *data, DataType dataType) { ListNode *newNode = createNode(data, dataType); if (!head) { return newNode; } ListNode *current = head; while (current->next) { current = current->next; } current->next = newNode; return head; } // 在链表指定位置插入节点 ListNode *insertNode(ListNode *head, void *data, DataType dataType, int position) { if (position == 0) { ListNode *newNode = createNode(data, dataType); newNode->next = head; return newNode; } ListNode *current = head; int i = 0; while (current && i < position - 1) { current = current->next; i++; } if (!current) { printf("Invalid position\n"); return head; } ListNode *newNode = createNode(data, dataType); newNode->next = current->next; current->next = newNode; return head; } // 删除指定位置的节点 ListNode *deleteNode(ListNode *head, int position) { if (!head) return NULL; if (position == 0) { ListNode *temp = head; head = head->next; freeNode(temp); return head; } ListNode *current = head; int i = 0; while (current && i < position - 1) { current = current->next; i++; } if (!current || !current->next) { printf("Invalid position\n"); return head; } ListNode *toDelete = current->next; current->next = toDelete->next; freeNode(toDelete); return head; } // 打印链表内容(根据数据类型) void printList(ListNode *head) { ListNode *current = head; printf("List: ["); while (current) { switch (current->dataType) { case INT_TYPE: printf("%d", *(int *)current->data); break; case FLOAT_TYPE: printf("%.2f", *(float *)current->data); break; case STRING_TYPE: printf("\"%s\"", *(char **)current->data); break; } if (current->next) { printf(" -> "); } current = current->next; } printf("]\n"); } // 释放整个链表 void freeListMemory(ListNode *head) { ListNode *current = head; while (current) { ListNode *temp = current; current = current->next; freeNode(temp); } // 释放空闲链表中的所有节点 while (freeList) { ListNode *temp = freeList; freeList = freeList->next; free(temp); } } // 主函数演示 int main() { ListNode *list = NULL; // 添加不同类型数据 int *num1 = malloc(sizeof(int)); *num1 = 10; list = appendNode(list, num1, INT_TYPE); float *num2 = malloc(sizeof(float)); *num2 = 3.14f; list = appendNode(list, num2, FLOAT_TYPE); char **str = malloc(sizeof(char *)); *str = strdup("Hello"); list = appendNode(list, str, STRING_TYPE); printList(list); // 插入新元素 int *num3 = malloc(sizeof(int)); *num3 = 20; list = insertNode(list, num3, INT_TYPE, 1); printList(list); // 删除元素 list = deleteNode(list, 2); printList(list); // 添加更多数据(可能重用空闲节点) float *num4 = malloc(sizeof(float)); *num4 = 7.89f; list = appendNode(list, num4, FLOAT_TYPE); printList(list); // 释放所有内存 freeListMemory(list); return 0; } ``` ## 关键特性说明 1. **可利用空间表(Free List)机制**: - `freeList`作为全局静态变量存储空闲节点 - `freeNode()`函数将删除的节点加入空闲链表 - `createNode()`优先重用空闲节点,减少内存分配次数[^2] 2. **函数重载模拟**: - 通过`dataType`枚举标识数据类型 - 使用`void*`通用指针存储不同类型数据 - 操作函数根据数据类型执行特定处理 - `printList()`函数通过switch-case区分不同数据类型的打印方式[^3] 3. **内存管理优化**: - 自定义分配(`createNode`)和释放(`freeNode`)策略 - 自动处理不同类型数据的释放要求 - 程序结束时可完全释放所有内存 ## 执行结果示例 ``` List: [10 -> 3.14 -> "Hello"] List: [10 -> 20 -> 3.14 -> "Hello"] List: [10 -> 20 -> "Hello"] List: [10 -> 20 -> "Hello" -> 7.89] ``` ## 复杂度分析 | 操作 | 时间复杂度 | 空间复杂度 | 说明 | |------------|------------|------------|--------------------------| | 插入(头插) | $O(1)$ | $O(1)$ | 直接更新头指针 | | 插入(中间) | $O(n)$ | $O(1)$ | 需要遍历到指定位置 | | 删除 | $O(n)$ | $O(1)$ | 可能需要遍历 | | 查找 | $O(n)$ | $O(1)$ | 需要顺序遍历链表 | | 打印 | $O(n)$ | $O(1)$ | 遍历所有节点 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值