C 语言链表
用 c 语言把链表的基本操作实现了一遍,节点数据的信息是「编号」、「姓名」和「年龄」,实现的功能有「链表的创建」「链表初始化」、「插入节点」、「链表的遍历」、「链表的销毁」、「查询节点」、「删除节点」,这里我就把这些函数贴在这里,做一个笔记,以后也可以查看。
定义数据结构:
typedef struct Person {
int number;
char name[50];
int age;
} Person_t;
typedef struct MLGB {
Person_t monster;
struct MLGB *next;
} MLGB_t;
typedef struct LinkList {
MLGB_t *head;
MLGB_t *tail;
int len;
} LinkList_t;
链表的初始化:
/*
初始化链表
*/
void init_link_list(LinkList_t *nnd) {
nnd->head = NULL;
nnd->tail = NULL;
nnd->len = 0;
return;
}
插入节点:
(一)、头部插入
/*
成功返回 0
失败返回 -1
*/
int insert_node_head(MLGB_t *cnm, LinkList_t *nnd) {
if (cnm == NULL || nnd == NULL) {
perror("空链表..\n");
return -1;
}
if (nnd->head == NULL) {
// 当前链表为空
nnd->head = cnm;
nnd->tail = cnm;
cnm->next = NULL;
nnd->len = 1;
return 0;
} else {
// 当前链表不为空
cnm->next = nnd->head;
nnd->head = cnm;
nnd->len++;
return 0;
}
return 0;
}
(二)、尾部插入
/*
尾部,节点插入
成功返回 0 ;失败返回 -1
*/
int insert_node_tail(MLGB_t *cnm, LinkList_t *nnd) {
if (cnm == NULL || nnd == NULL) {
perror("NULL 指针..\n");
return -1;
}
if (nnd->head == NULL) { // 链表为空
nnd->head = cnm;
nnd->tail = cnm;
cnm->next = NULL;
nnd->len = 1;
return 0;
} else {
nnd->tail->next = cnm;
nnd->tail = cnm;
cnm->next = NULL;
nnd->len++;
return 0;
}
return 0;
}
链表的遍历:
/*
遍历链表
返回链表的长度
*/
int show_link_list(LinkList_t *nnd) {
if (nnd->len == 0) {
printf("空链表。。\n");
}
MLGB_t *temp = NULL;
temp = nnd->head;
while (temp != NULL) {
printf("编号(number): %d\t姓名(name): %s\t年龄(age): %d\n",
temp->monster.number, temp->monster.name, temp->monster.age);
temp = temp->next;
}
return nnd->len;
}
销毁一个链表:
/*
销毁一个链表, 释放每个节点的内存,同时初始化链表为空
成功返回 0 ,失败返回 -1
*/
int destroy_linklist(LinkList_t *nnd) {
MLGB_t *current_p = NULL;
MLGB_t *temp_p = NULL;
current_p = nnd->head;
while (current_p != NULL) { // 删除当前节点
temp_p = current_p;
current_p = current_p->next;
free(temp_p);
}
init_link_list(nnd);
return 0;
}
查找一个节点:
/*
通过编号(number)查找节点
成功返回节点的地址
失败返回 NULL
*/
MLGB_t * query_node_by_number(LinkList_t *nnd, int number1) {
MLGB_t *current_p = NULL;
current_p = nnd->head;
while (current_p != NULL) {
if (current_p->monster.number == number1) {
// 找到节点
return current_p;
}
current_p = current_p->next;
}
return NULL;
}
删除一个节点:
/*
通过名字删除一个节点
成功返回 0
失败返回 -1
*node_point_del 用来保存被删除节点的地址
*/
int delete_by_name(LinkList_t *nnd, char *name1,
MLGB_t **node_point_del) {
MLGB_t *current_p = NULL; // 用来保存当前节点
MLGB_t *pre_p = NULL; // 用来保存前驱地址
current_p = nnd->head;
// 找节点
while (current_p != NULL) {
if (strcmp(current_p->monster.name, name1) == 0) {
if (current_p == nnd->head) {
// 要是删除的是头结点
nnd->head = nnd->head->next;
*node_point_del = current_p;
} else if (current_p == nnd->tail) {
// 如果是尾节点
nnd->tail = pre_p; // 指向前驱
pre_p = NULL;
*node_point_del = current_p;
} else {
pre_p->next = current_p->next;
*node_point_del = current_p;
}
nnd->len--;
return 0;
}
pre_p = current_p; // 记下 current_p 的前驱
current_p = current_p->next;
}
printf("没能找到 %s 的信息..\n", name1);
*node_point_del = NULL;
return -1;
}
程序运行:
写个主程序测试一些功能,功能都实现了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了