ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数据结构学习笔记(六)--双链表.md

2022-07-05 21:31:08  阅读:135  来源: 互联网

标签:md 结点 return -- next 双链 NULL DNode


数据结构学习笔记(六)--双链表.md

因为单链表无法逆向检索,有时候会不太方便,故有双链表的数据结构。

点击进入上一篇:数据结构学习笔记(五)--单链表

双链表的定义

可理解为比单链表多了一个指向前驱结点的指针,这里不再赘述。

用代码定义一个双链表

和单链表相比多了一个指向前驱的指针,用c/c++实现,如下:

typedef struct DNode{ //定义双链表节点类型
    int data; //每个节点存放一个整型元素
    struct DNode *prior,*next; //前驱和后继指针
} DNode, *DLinkList;

初始化一个双链表

带头结点

用C/C++表示,如下:

//初始化双链表(带头结点)
bool InitDLinkList(DLinkList &L){
    L = (DNode *) malloc(sizeof(DNode)); //分配一个头结点
    if(L == NULL) //内存不足,分配失败
        return false;
    L->prior = NULL; //头结点的prior永远指向NULL
    L->next = NULL; //头结点之后暂时还没有结点
    return true;
}

判断是否为空

用C/C++表示,如下:

//判断双链表是否为空(带头结点)
bool Empty(DLinkList L){
        return (L->next == NULL);
}

不带头结点

这里是自己写的不是课上笔记,仅供参考。

用C/C++表示,如下:

//初始化双链表(不带头结点)
bool InitDLinkList(DLinkList &L){
    L = NULL; //空表,暂时还没有任何节点(防止脏数据)
    return true;
}

判断是否为空

用C/C++表示,如下:

//判断双链表是否为空(不带头结点)
bool Empty(DLinkList L){
        return (L == NULL);
}

双链表的基本操作

以下默认为带头结点的操作。

插入

这里写一个最终要的后插操作,具体逻辑看代码,不做赘述。注意判断如果插在最后一个结点时的特殊情况。

代码实现

用C/C++表示,如下:

/**
 * @brief 在p结点之后插入s结点
 * 
 * @param p 
 * @param s 
 * @return true 
 * @return false 
 */
bool InsertNextDNode(DNode *p,DNode *s){
    if (p==NULL || s==NULL) //非法参数
        return false;
    s->next = p->next;
    if(p->next != NULL)
        p->next->prior = s; //如果p结点有后继结点
    s->prior = p;
    p->next = s;
    return true;
}

时间复杂度

​ 个人认为是O(1)

除后插外其他插入的实现

由于双链表可逆向检索,所以其他插入的逻辑变得简单,核心逻辑依旧为后插,如:

  • 按位序插入:遍历到指定位序后,根据指定位序的前驱指针指向前驱结点,再到前驱结点执行后插操作。
  • 前插插入,根据指定结点的前驱指针指向前驱结点,再到前驱结点执行后插操作。在带头结点的情况下,表头前插并不需要考虑特殊情况

删除

删除指定结点的后继结点

用C/C++表示,如下:

/**
 * @brief 删除p结点的后继结点
 * 
 * @param p 
 * @return true 
 * @return false 
 */
bool DeleteNextDNode(DNode *p){
    if (p==NULL) return false;
    DNode *q = p->next; //找到p的后继结点q
    if (q == NULL) return false; //p没有后继
    p->next = q->next;
    if (q->next!=NULL) //q结点不是最后一个结点
        q->next->prior = p;
    free(q);
    return true;
}

销毁整个双链表

遍历整张表,调用删除后继结点的方法即可。C/C++表示,如下:

/**
 * @brief 销毁双链表
 * 
 * @param L 
 */
void DestoryList(DLinkList &L){
    //循环释放各个数据结点
    while(L->next != NULL)
        DeleteNextDNode(L);
    free(L); //释放头结点
    L = NULL; //头指针指向NULL
}

时间复杂度不在赘述,自行揣摩。

遍历

分为指定结点向后或向前,过于简单所以不做赘述,如图所示。

image-20220705212209294

标签:md,结点,return,--,next,双链,NULL,DNode
来源: https://www.cnblogs.com/yibener18/p/16448707.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有