【C】链表的创建、打印、插入、删除等

链表两个概念:

1.普通链表 data定义数据类型指针(不够灵活)

2.通用链表 data定义void*(可以接受任何数据类型的指针地址)

注意:头结点是哨兵结点,没有数据及其地址

1.创建结点

通过结构体定义一个结点:

typedef struct node_t

{

int val;//记录节点链表的位置

void *data;//存放数据字段

struct node_t *pnext;//下一结点地址

}NODE_T;

2.创建链表,返回头结点

步骤:

1.创建一个链表结点

2.开辟内存,并去清空内存(可以使用calloc函数,malloc不能清理内存)

3.赋值

NODE_T *List_Init()

{

//1.创建一个链表结点

NODE_T *head=NULL;//一开始指向0,需要开内存

//开辟内存

// head=(NODE_T *)malloc(sizeof(NODE_T));//未清空内存

head=(NODE_T *)calloc(1,sizeof(NODE_T));//开辟空间,清空内存

if(head==NULL)

{

printf("开辟内存空间失败!\n");

return NULL;

}

head->data=NULL;

head->pnext=NULL;

head->val=0;

return head;

}

3.链表添加结点(默认尾插)

把节点添加到链表

head:头结点指针 data:要插入数据地址

void List_Add(NODE_T *head,void *data)

{

NODE_T *ptmp=head;//保存头结点

NODE_T *newNode=NULL;

int tmp_val=0;

//找到链表尾部结点

while(ptmp->pnext!=NULL)

{

tmp_val=ptmp->val;

ptmp=ptmp->pnext;

}

//在内存中开辟新节点空间

newNode=(NODE_T *)calloc(1,sizeof(NODE_T));

newNode->data=data;

newNode->val=++tmp_val;

newNode->pnext=NULL;

ptmp->pnext=newNode;

}

4.打印链表

里面的数据data,因为定义无类型指针,这里指向结构体

void printList(NODE_T *head)

{

NODE_T *ptmp=head;

while(ptmp!=NULL)

{

if(ptmp->data!=NULL)

{

printf("age=%d\n",((PACK_T*)(ptmp->data))->age);

}

ptmp=ptmp->pnext;

}

}

5.获取链表的结点个数

获取链表有多少结点,链表第一个结点data无数据,叫哨兵结点

int getListCount(NODE_T *head)

{

int count=0;

NODE_T *ptmp=head;

while(ptmp->pnext!=NULL)

{

count++;

ptmp=ptmp->pnext;

}

return count;//链表有效结点的个数

}

6.插入结点(尾插)

pos:第几个结点,data:插入的数据

int insertList(NODE_T *head,int pos,void *data)

{

NODE_T *ptmp=head;

NODE_T *newNode=NULL;

int num=0;

//1.找pos在链表位置

while(ptmp->pnext!=NULL)

{

ptmp=ptmp->pnext;//跳开哨兵结点

num++;

if(num==pos)

{

newNode=(NODE_T*)calloc(1,sizeof(NODE_T));

if(newNode==NULL)

{

printf("calloc error!\n");

exit(0);

}

newNode->data=data;

//以下两个顺序不能颠倒

newNode->pnext=ptmp->pnext;

ptmp->pnext=newNode;//指向新的

return 0;

}

}

return -1;

}

7.删除指定结点

1.找到要删除的结点位置,要保存前一个结点指针

2.定义两个指针,pre:前个结点

int deleteNodeByPos(NODE_T *head,int pos)

{

//找到要删除的结点位置

//要保存前一个结点指针

//定义两个指针,pre:前个结点

NODE_T *ptmp=head->pnext,*pre=head;

int num=0;

while(ptmp!=NULL)

{

num++;

if(num==pos)

{

pre->pnext=ptmp->pnext;//把前一个结点指向后一个结点

free(ptmp);

return 1;

}

//如果不是匹配的位置ptmp与pre往后移

pre=pre->pnext;

ptmp=ptmp->pnext;

}

return -1;

}

8.指定位置返回数据

void *getListDataByPos(NODE_T *head,int pos)

{

NODE_T *ptmp=head;

int num=0;

while(ptmp->pnext!=NULL)

{

ptmp=ptmp->pnext;

num++;

if(num==pos)

{

return ptmp->data;

}

}

return NULL;

}

9.释放整个链表

void freeList(NODE_T *head)

{

NODE_T *ptmp=head;

while(ptmp!=NULL)

{

head=head->pnext;//首相移动到下一个结点

free(ptmp);//可以释放ptmp,因为ptmp还是指向移动之前的结点

ptmp=head;//再把移动后的结点赋值ptmp

}

}

相关推荐
hsjiasb2 小时前
FreeRTOS学习(二十七)——任务栈与栈溢出检测
开发语言·stm32·学习·学习笔记·freertos
小弥儿2 小时前
GitHub今日热榜 | 2026-08-16:大模型微调与编码工具扎堆
学习·开源·github
丰锋ff2 小时前
3.1 Qt事件之事件处理器
开发语言·qt
多弗朗皮卡丘3 小时前
C语言梦开始的地方7:函数
c语言·开发语言
月华路3 小时前
G1 垃圾回收:脏卡队列、记忆集与并发精化线程机制
java·开发语言
2501_926978333 小时前
AGI 的四种瓶颈:资源型还是发现型--以及DSH的位置
人工智能·经验分享·笔记·ai写作
gugucoding4 小时前
47. 【Java】Java内存模型(JMM)与可见性
java·开发语言
m0_380743874 小时前
从零调用 Claude 教程
开发语言·python·node.js
起床学FPGA4 小时前
AI回答问题之后,会自动跳到最下面的问题
开发语言·javascript·ecmascript
liuqs3324 小时前
nat123安卓和nat123全端口选型指南,映射工具怎么挑
网络·笔记