单链表
所有元素没有紧挨在一起,但每个元素知道下一个元素的地址
定义:
struct Node
{
DataType d;
struct Node *next;
};
单链表思路图:
我会在下面附上单链表代码,有增、删、查、改、倒置、打印功能,并且尽量加上注释,如果还有不懂可以在评论区留言,我会尽我所能解答
单链表代码:
link.h 头文件,用来定义结构体,声明函数
#ifndef __Link_H__ //如果不存在则定义以下内容
#define __Link_H__
#include <stdbool.h>
typedef int dType; //重命名int为dType,方便改数据类型
typedef struct Node //定义一个单链表
{
dType s;
struct Node *next;
}node,*pnode; //重命名
//声明函数,添加,打印,查找,更改,删除,倒置
//add
extern bool add(pnode*,student);
//list
extern void list(pnode);
//find
extern pnode find(pnode,char*);
//update
extern bool update(pnode,char*,student);
//drop
extern bool drop(pnode*,char*);
//rease
extern void rease(pnode *pph,pnode first,pnode second,pnode third);
#endif
link.c 主要函数文件,写实现方法,被调用
#include <stdio.h> //标准库
#include <stdlib.h> //堆区
#include "link.h" //自定义头文件
bool add(pnode *pph,Dtype d) //头插法,增加一个链表元素
{
pnode pn=NULL; //创建新的节点
pn=malloc(sizeof(node)); //分配堆区空间
if(NULL==pn) //分配失败返回false
return false;
pn->d=d; //填充内容
pn->next=*pph;
*pph=pn; //让头结点指向该节点
return true; //返回true
}
void list(pnode ph) //打印
{
while(NULL!=ph) //头节点不为空
{
printf("%d ",ph->d); //打印内容
ph=ph->next; //指向下一个节点
}
printf("\n");
}
pnode find(pnode ph,Dtype d) //查找元素,返回节点指针
{
while(NULL!=ph && d!=ph->d) //节点不为空,且数据不相等,指向下一个节点
ph=ph->next;
return ph; //返回ph,若没找到ph指向NULL,返回也为空
}
bool update(pnode ph,Dtype oldd,Dtype newd) //更新
{
pnode pn=NULL; //创建新的节点
if((pn=find(ph,oldd))==NULL) //调用查找函数,若没找到返回false
return false;
pn->d=newd; //否则,更新数据
return true; //返回true
}
bool drop(pnode *pph,Dtype key) //删除,前一个节点指向下一个节点
{
//创建两个节点,用来找到前一个的节点(first)与当前节点(ploc)
pnode first=NULL,ploc=*pph;
while(ploc!=NULL && ploc->d!=key) //循环查找需要删除的节点,first始终指向ploc上一个节点
{
first=ploc;
ploc=ploc->next;
}
if(NULL==ploc) //循环结束后若ploc等于NULL,说明没有改元素
return false; //返回false
else if(ploc==*pph) //否则如果ploc==头指针,说明第一个元素就是需要删除的
*pph=ploc->next; //让头指针直接指向下一个节点
else //否则就是找到该元素,且不是第一个
first->next=ploc->next; //让前一个节点指向下一个节点
free(ploc); //释放堆区,一定不要忘记
return true; //删除成功返回true
}
void rease(pnode *pph,pnode first,pnode second,pnode third) //递归倒置
{
//先让first,second=NULL,third=头结点,然后每次往后移动一个元素
//主要对second进行判断,让second一直指向前一个元素,让third起到一直读取的作用
if(NULL!=second) //second不等于NULL,则让second指向first(前一个元素)
second->next=first;
if(NULL==third) //递归结束条件,third已经指向了空,这时second指向最后一个元素
//则让头结点指向second,结束递归
{
*pph=second;
return;
}
rease(pph,second,third,third->next);
//调用自己,first指向second,second指向third,third指向third的next
}
main.c 主文件,用来调用函数,测试链表
#include <stdio.h> //标准库
#include "link.h" //自定义头文件
int main()
{
pnode head=NULL; //定义头节点
printf("添加1,2,3,4\n");
add(&head,1);
add(&head,2);
add(&head,3);
add(&head,4);
list(head);
printf("-------------------------\n");
printf("查找元素:2\n");
pnode pf=NULL;
if((pf=find(head,2))!=NULL)
printf("%d\n",pf->d);
else
printf("not found\n");
printf("-------------------------\n");
printf("更改元素2—>5\n");
if(update(head,2,5))
printf("success\n");
else
printf("fail\n");
list(head);
printf("-------------------------\n");
printf("删除元素:4\n");
drop(&head,4);
list(head);
printf("-------------------------\n");
rease(&head,NULL,NULL,head);
list(head);
return 0;
}
程序运行结果:
头插法,所以存放数据会像栈一样存入