C语言自定义MyList结构体封装链表移除全局变量的改造方法
链表封装改造方案
核心改动逻辑很直接:把原来散落在全局的链表状态(头指针、元素计数)收拢到你定义的struct MyList结构体中,所有操作链表的函数不再依赖全局变量,改为接收链表结构体指针作为入参,直接操作对应实例的成员即可。改造过程中顺便修复了原代码里的3个隐性bug:
- 原
deleteFirst函数把计数递减逻辑写在了return语句之后,永远不会执行,会导致长度统计错误 - 原
delete函数进入函数就直接递减计数,当找不到待删除节点直接返回时,计数会不准 - 原代码用
void main()不符合C语言标准,改为标准的int main()返回值格式
改造后可直接运行的完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> // 节点结构体定义保持不变 struct node { int data; int key; struct node *next; }; // 自定义链表结构体,收拢原来的全局状态 struct MyList { struct node *head; int numberOfElements; }; // 遍历打印链表,入参为目标链表指针 void printList(struct MyList *list) { struct node *ptr = list->head; printf("\n[ "); while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } printf(" ]"); } // 链表头部插入节点 void insertFirst(struct MyList *list, int key, int data) { struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; // 新节点指向原头节点 link->next = list->head; // 更新链表头指针为新节点 list->head = link; list->numberOfElements ++; } // 删除链表头节点 struct node* deleteFirst(struct MyList *list) { // 空链表直接返回NULL if (list->head == NULL) { return NULL; } struct node *tempLink = list->head; // 头指针后移 list->head = list->head->next; list->numberOfElements --; return tempLink; } // 判断链表是否为空 bool isEmpty(struct MyList *list) { return list->head == NULL; } // 返回链表长度 int length(struct MyList *list) { return list->numberOfElements; } // 按key查找节点 struct node* find(struct MyList *list, int key) { struct node* current = list->head; if(list->head == NULL) { return NULL; } while(current->key != key) { if(current->next == NULL) { return NULL; } else { current = current->next; } } return current; } // 按key删除指定节点 struct node* delete(struct MyList *list, int key) { struct node* current = list->head; struct node* previous = NULL; if(list->head == NULL) { return NULL; } while(current->key != key) { if(current->next == NULL) { return NULL; } else { previous = current; current = current->next; } } // 确认找到节点后再更新计数,避免找不到节点时计数错误 list->numberOfElements --; if(current == list->head) { list->head = list->head->next; } else { previous->next = current->next; } return current; } int main() { // 初始化一个链表实例,初始状态头指针为空、元素数为0 struct MyList my_list = { .head = NULL, .numberOfElements = 0 }; // 所有链表操作都传入目标链表的指针 insertFirst(&my_list,1,10); insertFirst(&my_list,2,20); insertFirst(&my_list,3,30); insertFirst(&my_list,4,1); insertFirst(&my_list,5,40); insertFirst(&my_list,6,56); printf("Original List: "); printList(&my_list); printf("\nlength is %d\n",length(&my_list)); struct node *foundLink = find(&my_list,4); if(foundLink != NULL) { printf("\nElement found: "); printf("(%d,%d) ",foundLink->key,foundLink->data); printf("\n"); } else { printf("Element not found."); } delete(&my_list,4); printf("List after deleting an item: "); printList(&my_list); printf("\n"); foundLink = find(&my_list,4); if(foundLink != NULL) { printf("\nElement found: "); printf("(%d,%d) ",foundLink->key,foundLink->data); printf("\n"); } else { printf("Element not found."); } printf("\nlength is %d\n",length(&my_list)); return 0; }
额外说明
改造完成后可以在代码里同时创建多个struct MyList实例,各个实例的节点、长度完全独立互不影响,这也是去掉全局变量、封装链表结构体带来的直接好处。如果需要动态创建链表,也可以写一个配套的初始化函数,用malloc申请struct MyList的内存后完成初始值赋值即可。
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

