数据结构双循环链表头插法尾插法和删除练习

#include<stdio.h>
#include<stdlib.h>
typedef struct list {
int data;
struct list* pre;
struct list* next;
}list;
list* init() {
list* L = (list*)malloc(sizeof(list));
L->data = 0;//链表节点个数为0
L->pre = L;//双循环链表自己指自己
L->next = L;//同上
return L;
}
void headIns(list* L, int data) {//将头指针传入
list* S = (list*)malloc(sizeof(list));
S->data = data;
if (L->data == 0) {//链表为空情况
//画图更直观看到结点指针的变化情况
S->pre = L;
S->next = L->next;
L->next = S;
L->pre = S;
L->data++;
}
/下面是常规的左右都有结点时的插入方式/
/采用先后再前的插入方式/
else {//链表非空
S->next = L->next;
S->pre = L;
L->next->pre = S;
L->next = S;
L->data++;
}
}

void tailIns(list* L, int data) {
list* S = (list*)malloc(sizeof(list));
list* zj = L;//尾插法需要一个中间节点来进行记录
S->data = data;
while (zj->next!=L) {
zj = zj->next;
}
//规范书写<尾对头><头对尾>
S->pre = zj;
S->next = L;
L->pre = S;
zj->next=S;//顺序似乎并不影响?
zj = S;//此步不是必须,只是简化while判断次数
L->data++;//L加一,没有其他作用
}
//但是由于双链表已经有前指针所以无需定义preS

void delet(list* L, int data) {
//list* preS = L;
list* S = L->next;
while (S!=L) {//循环的判断条件不能时while(S),因为循环类的用不为空
if (S->data == data) {
S->pre->next = S->next;//S的前一个节点的后继指向S的后继
S->next->pre = S->pre;//S的后一个节点的前驱指向S的前驱
L->data–;
//free(S);//VS2022报错,其他编译器可正常执行
}
//else //不能加else
S = S->next;
}
}
void show(list* L) {
list* S=L->next;//L->next是其第一个数据节点
//L本身第一个节点只是头结点没有特殊含义
while (S!=L)
{
printf("%d\n", S->data);
S = S->next;
}
}
int main() {
list* L = init();
headIns(L, 1);
headIns(L, 3);
headIns(L, 5);
tailIns(L, 7);
tailIns(L, 8);
tailIns(L, 9);
show(L);
printf("*************\n");
delet(L, 9);
show(L);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值