【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

}

}

相关推荐
charlie1145141913 分钟前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(OLED设备层封装)
c语言·stm32·单片机·教程·oled·嵌入式软件
张太行_4 分钟前
C++中的析构器(Destructor)(也称为析构函数)
开发语言·c++
小林up1 小时前
【C语言设计模式学习笔记1】面向接口编程/简单工厂模式/多态
c语言·设计模式
SteveKenny2 小时前
Python 梯度下降法(六):Nadam Optimize
开发语言·python
Hello.Reader3 小时前
深入浅出 Rust 的强大 match 表达式
开发语言·后端·rust
涛ing4 小时前
32. C 语言 安全函数( _s 尾缀)
linux·c语言·c++·vscode·算法·安全·vim
__雨夜星辰__5 小时前
Linux 学习笔记__Day2
linux·服务器·笔记·学习·centos 7
学问小小谢5 小时前
第26节课:内容安全策略(CSP)—构建安全网页的防御盾
运维·服务器·前端·网络·学习·安全
xrgs_shz5 小时前
MATLAB的数据类型和各类数据类型转化示例
开发语言·数据结构·matlab