【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

}

}

相关推荐
梓仁沐白1 分钟前
【Kotlin】注解&反射&扩展
开发语言·python·kotlin
@老蝴12 分钟前
C语言 — 编译和链接
c语言·开发语言
本郡主是喵1 小时前
并发编程 - go版
java·服务器·开发语言
冷凌爱1 小时前
总结HTML中的文本标签
前端·笔记·html
努力学习的小廉1 小时前
我爱学算法之—— 前缀和(中)
开发语言·redis·算法
保持学习ing1 小时前
黑马Java面试笔记之 集合篇(算法复杂度+ArrayList+LinkedList)
java·笔记·算法·面试
LunaGeeking1 小时前
三分算法与DeepSeek辅助证明是单峰函数
c语言·c++·算法·编程·信奥赛·ai辅助学习·三分
想带你从多云到转晴2 小时前
02. java: 类与对象
java·开发语言
Moonnnn.2 小时前
【单片机期末】串行口循环缓冲区发送
笔记·单片机·嵌入式硬件·学习
abments2 小时前
基于ReAction范式的问答系统实现demo
开发语言·python