其他分享
首页 > 其他分享> > 数据结构学习笔记(六)--双链表.md

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

作者:互联网

数据结构学习笔记(六)--双链表.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