You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 22:39:19