【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

}

}

相关推荐
Fanxt_Ja2 天前
【LeetCode】算法详解#15 ---环形链表II
数据结构·算法·leetcode·链表
侃侃_天下2 天前
最终的信号类
开发语言·c++·算法
_落纸2 天前
三大基础无源电子元件——电阻(R)、电感(L)、电容(C)
笔记
echoarts2 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
Alice-YUE2 天前
【CSS学习笔记3】css特性
前端·css·笔记·html
2303_Alpha2 天前
SpringBoot
笔记·学习
Aomnitrix2 天前
知识管理新范式——cpolar+Wiki.js打造企业级分布式知识库
开发语言·javascript·分布式
萘柰奈2 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
沐矢羽2 天前
Tomcat PUT方法任意写文件漏洞学习
学习·tomcat
好奇龙猫2 天前
日语学习-日语知识点小记-进阶-JLPT-N1阶段蓝宝书,共120语法(10):91-100语法+考え方13
学习