回看了一下以前写的链表操作,确实有点复杂不利于初学,这篇文章就换个写法,简单明了的介绍链表的操作;
第一步:定义节点结构体,可以把它看成一个模板:
// 定义节点typedef struct node{ unsigned char data; struct node *next;}node_t;
第二步:初始化节点,目的就是获取到头节点,后续的操作都是判断节点的同名结构体指针是否为空,所有头节点的head->next必须等于null:
// 初始化节点node_t* node_init(unsigned char data){ node_t* head=(node_t*)malloc(sizeof(node_t)); head->data = data; head->next = null; return head;}
第三步:打印节点数据,用于查看节点的最新数据:
// 打印链表void node_printf(node_t *node){ node_t *head = node; while(1){ printf(data:%d,head->data); if(head->next==null){ return; }else{ head = head->next; } };}
第四步:尾插方式把新的节点接入链表,核心就是判断节点的指针是否为空,找到最尾巴的节点,然后把新的节点接到它的后面,然后再把新的节点指针赋值为空:
// 尾插node_t* node_end_add(node_t *node, unsigned char data){ node_t *head = node; node_t *end = node; while(1){ if(end->next!=null){ end = end->next; }else{ node_t* temp_node=(node_t*)malloc(sizeof(node_t)); temp_node->data = data; temp_node->next = null; end->next = temp_node; return head; } }}
第五步:通过尾删的方式,把节点指针为空的节点删除,再把它上一个节点赋值为空:
// 尾删node_t* node_end_del(node_t *node){ node_t *head = node; node_t *end = node; node_t *temp = null; while(1){ if(end->next!=null){ temp = end; end = end->next; }else{ free(end); temp->next = null; return head; } }}
第六步:通过头插方式,把新的节点接入到链表,头插的方式并不需要赋值为空,因为它插入的下一节点,就是上一次插入的节点指针,所以只需要把上一个节点指针赋值给新加入的指针即可,注意头插一定要返回头节点指针,因为头插的头节点会随着插入而改变:
// 头插node_t* node_head_add(node_t *node, unsigned char data){ node_t* temp_node=(node_t*)malloc(sizeof(node_t)); temp_node->data = data; temp_node->next = node; return temp_node;}
第七步:通过头删的方式,把头部的节点删除,因为头部的节点是已知的,所以只要改表一下头节点,然后把头部节点释放就可以:
// 头删node_t* node_head_del(node_t *node){ node_t* head = node->next; free(node); return head;}
总结:尾节点操作是通过判断节点指针是否为null,找到节点指针为null的指针,然后进行相关操作,而头节点直接就通过头节点进行相关操作,头插和尾插最大的不同就是数据是反的,这点要注意不要搞错;
完整代码如下:
#include stdio.h#include stdlib.h// 定义节点typedef struct node{ unsigned char data; struct node *next;}node_t;// 初始化节点node_t* node_init(unsigned char data){ node_t* head=(node_t*)malloc(sizeof(node_t)); head->data = data; head->next = null; return head;}// 打印链表void node_printf(node_t *node){ node_t *head = node; while(1){ printf(data:%d,head->data); if(head->next==null){ return; }else{ head = head->next; } };}// 尾插node_t* node_end_add(node_t *node, unsigned char data){ node_t *head = node; node_t *end = node; while(1){ if(end->next!=null){ end = end->next; }else{ node_t* temp_node=(node_t*)malloc(sizeof(node_t)); temp_node->data = data; temp_node->next = null; end->next = temp_node; return head; } }}// 尾删node_t* node_end_del(node_t *node){ node_t *head = node; node_t *end = node; node_t *temp = null; while(1){ if(end->next!=null){ temp = end; end = end->next; }else{ free(end); temp->next = null; return head; } }}// 头插node_t* node_head_add(node_t *node, unsigned char data){ node_t* temp_node=(node_t*)malloc(sizeof(node_t)); temp_node->data = data; temp_node->next = node; return temp_node;}// 头删node_t* node_head_del(node_t *node){ node_t* head = node->next; free(node); return head;}int main(){ node_t* user_node = node_init(1); // 尾 // user_node = node_end_add(user_node, 2); // user_node = node_end_add(user_node, 3); // user_node = node_end_add(user_node, 4); // node_printf(user_node); // printf(------); // user_node = node_end_del(user_node); // user_node = node_end_del(user_node); // node_printf(user_node); // printf(------); // user_node = node_end_add(user_node, 3); // user_node = node_end_add(user_node, 4); // node_printf(user_node); // printf(------); // 头 user_node = node_head_add(user_node, 2); user_node = node_head_add(user_node, 3); user_node = node_head_add(user_node, 4); node_printf(user_node); printf(------); user_node = node_head_del(user_node); user_node = node_head_del(user_node); node_printf(user_node); printf(------); user_node = node_head_add(user_node, 3); user_node = node_head_add(user_node, 4); node_printf(user_node); printf(------);}
代码写得不是很严谨,主要用于入门学习,把主要思路讲清楚;觉得有收获的同学动动小手指点个赞吧,我是noah,我们下篇推文再见!
AI学习要从娃娃抓起吗?
【虹科干货】如何用AI视觉助力质量检测
VR与模拟技术助汽车制造业简化开发流程
荣耀V20与小米9耗电效率对比
区块链的平台会取代传统的交互模式吗
链表的基本操作
如何查找多列上的重复行
Synopsys以本地环境重新定义电路仿真
三星A60曝光搭载骁龙675移动平台并采用了屏下指纹解决方案
光电三极管的作用和特点
德州仪器LMK0480X holdover的功能分析
基于高线性混频器MAX9994实现侦测接收通道的设计方案
荣耀8青春版:最美华为手机,骚气外表+强悍配置+1099
Intel发布一款特别版酷睿i9-9900KS 全核最高5.0GHz
科技金融生态呈现创业风险投资更加活跃的特性
谷歌和Facebook仍是美国移动应用市场的主宰
怎样用手机控制电源适配器
OpenAI首届开发者日举办,新模型实现六大升级
意法半导体推出创新的汽车仪表盘用数字放大器
CVPR 2023论文总结!CV最热领域颁给多模态、扩散模型