双向链表 :
拥有两个方向:
从头到尾/从尾到头
线性结构 + 链式存储
拥有一个数据域 + 两个指针域
其中一个指针域保存下一个节点的地址
另一个指针域保存上一个节点的地址
结构体模板:
typdef struct link{
int data; //数据域
struct link *prev;//前指针域:上一个节点的地址
struct link *next;//后指针域:下一个节点的地址
}link_t,*plink_t;
逻辑操作
1.创建一个节点
plink_t create_node(int d)
{
plink_t p = (plink_t)malloc(sizeof(link_t));//创建节点p,分配空间
if(p==NULL)
{
perror("malloc error");
return NULL;
}
//初始化节点
p->data = d;//将外部传入的d,赋值到节点的数据域上
p->prev=NULL;//目前节点没有进入链表,所以初始化为NULL
p->next=NULL;//目前节点没有进入链表,所以初始化为NULL
return p;
}
建立一个结构体指针用来接收 头节点的地址
plink_t head = link_init();
plink_t link_init(){
return creat_node(-1);
}
2.头插操作:新节点固定插入到头节点的后面
void link_insert_head(plink_t p,int d)
{
//1>通过接收到的数据创建节点
plink_t node=create_node(d);
if(node==NULL){
return;
}
//2>将node节点插入到 头节点的后面 --->头插
insert_tail(p,node);
}
2.尾插操作:新节点固定插入到 链表的末尾
void link_insert_tail(plink_t p,int d)
{
plink_t node=create_node(d);
if(node==NULL){
return;
}
//将位置跳转到尾巴
while(p->next!=NULL)
p=p->next;
//将节点插入到尾巴
insert_tail(p,node);
}
将位置跳转到尾巴 p=p->next;
插入函数 关键!!!
void insert_tail(plink_t p,plink_t node)
{
node->next=p->next;
node->prev=p;
if(p->next!=NULL)
p->next->prev=node;
p->next=node;
}
/*这里做if判断的作用是:有可能p节点是链表的最末尾节点,由于该链表不是循环链表,所以最末尾节点p节点的下一个节点(即:p->next)为空节点(NULL),由于空节点是没有数据域和指针域的,所以也就不存在下面C语句p->next->prev,所以这里需要判断一下。如果p节点为末尾节点,那么就执行 p->next->prev = node;这句话。如果该链表是循环链表,那么这里就不需要进行if判断了*/
原文链接:https://blog.csdn.net/qq_39577221/article/details/124789642
3.遍历双链表中的数据
void display(plink_t p)
{
printf("遍历结果为:");
while(p->next!=NULL){
p=p->next;
printf("%d ",p->data);
}
printf("\n");
}
4.逆序遍历
void n_display(plink_t p)
{
printf("逆序遍历结果为:");
while(p->next!=NULL){
p=p->next;
}
while(p->prev!=NULL){
printf("%d ",p->data);
p=p->prev;
}
printf("\n");
}
5.删除操作:通过数据域找到要删除的数据,并删除节点
void link_del(plink_t p,int d)
{
//1>判断输入的数据,是否满足链表中的某个数据域
while(p->next!=NULL){
p=p->next;
if(p->data==d){//如果满足该条件,说明找到了要删除的数据
node_del(p);
return;
}
}
printf("助教%d号没有上班\n",d);
}
6.替换操作:根据数据域new创建一个节点,用新节点替换旧节点
void link_update(plink_t p,int old,int new)
{
//1>遍历查找数据是否存在和old匹配的数据域
while(p->next!=NULL){
p=p->next;
if(p->data==old){//满足条件,说明找到了
plink_t new_node=create_node(new);//根据新数据创建新节点
if(new_node==NULL)
return;
update(p,new_node);
return;
}
}
printf("没找到助教%d,换一批\n",old);
}