双向链表

本文介绍了双向链表的基本概念,包括其结构特点、节点组成及如何通过前驱和后继节点进行访问。此外还详细讲解了如何创建双向链表、进行节点的插入与删除等关键操作。

学习了前面的单链表之后再学习双向链表就容易理解多了。

概况

在双向链表中,一个节点保存了它前面一个节点,和后面一个节点的索引,可以向前访问,和向后访问。
和单链表比较起来,向前访问更加的方便。

单个节点

这里写图片描述
在一个节点中呢分为三个区域,第一个区域为prior用来保存前驱节点的地址,第二个区域保存节点中的数据,第三个区域next用来保存后继节点的地址,因为一个节点中保存了前驱和后继节点,那么这个节点就可以通过变量prior和next来分别访问前后节点。

成链

这里写图片描述
要注意的是,上图为双循环链表,完全可以根据自己的需求来设计双向链表,人是活的嘛。

创建链表

typedef struct node{
    int data;
    struct node *prior;
    struct node *next;
}node;

node *create(int n){
    //创建头节点
    node *head = (node*)malloc(sizeof(node));
    //将移动的p指针指向头节点,以后p都会指向最后一个节点
    node *p = head;
    //初始化头节点
    head->prior = NULL;
    head->next = NULL;
    int i;
    //初始化数据
    for(i = 1; i <= n; i++){
        //创建新的节点
        node *s = (node*)malloc(sizeof(node));
        //写入数据
        s->data = i;
        //将新的的节点的前驱指向为最后一个节点
        s->prior = p;
        //将最后一个节点的后继节点指向为新的节点
        p->next = s;
        //连接成功后又将p指向新的节点(也是现在链表的最后一个节点)
        p = s;
    }
    //将最后一个节点的后继节点指向为头节点
    p->next = head;
    //将头节点的前驱指向为最后一个节点节点,在这里形成环
    head->prior = p;
    return head;

}

插入操作

这里写图片描述

void insert(node *head,int index, int data){
    node *target;
    //查找标记
    int count = 1;
    //使用for循环查找对应位置
    for(target = head->next; target != head; target = target->next,count++){
        if(count == index){
            //创建新的的节点
            node *s = (node*)malloc(sizeof(node));
            s->data = data;
            /*第一步,将新节点的后继指向目标位置,表示将新节点插入
            目标节点的前面*/
            s->next = target;
            //第二步,新节点的前驱节点指向为目标节点的前驱节点
            s->prior = target->prior;
            //第三步,目标节点的前驱节点后继节点指向为新节点
            target->prior->next = s;
            //第四步,目标节点的前驱节点设置为新节点
            target->prior = s;
        }
    }
}

注意上面的顺序很重要,比如,如果先执行第四步,那么我们就不能够通过目标节点的前驱节点找到目标节点的前一个节点,整个链也就断了。

删除操作

这里写图片描述

void deleteNode(node *head, int index){
    node *target;
    //查找标记
    int count = 1;
    //使用for循环查找对应位置
    for(target = head->next; target != head; target = target->next,count++){
        if(count == index){
            //第一步
            target->prior->next = target->next;
            //第二步
            target->next->prior = target->prior;
            free(target);
        }
    }
}

在理解了插入节点的基础上,理解删除就很容易了,断绝目标节点和他相邻节点的关系就OK啦,最后别忘记了重新连接两个相邻节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值