数据结构——双向链表的插入遍历及删除

目录

一、单链表和双链表

二、双链表的初始化(带头结点)

三、双链表的插入

四、双链表的删除

五、双链表的遍历

 


一、单链表和双链表

单链表:无法逆向检索,不方便

双链表:可进可退,存储密度更低

双链表的结构体定义

typedef struct DNode{        //定义双链表结点类型
    ElemType data;        //数据域
    struct DNode *prior,*next;        //前驱和后继指针
}DNode *,DLinklist;

 

二、双链表的初始化(带头结点)

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

void testDLinkList(){
    DLinklist L;
    InitDLinkList(L);
}

注:DLinklist 等价于  DNode *,一个强调是个双链表,一个强调是结点

 

三、双链表的插入

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

思路:

1.当插入链表的末尾时

①s的后继指针指向p的后继指针

②s的前驱指针指向p

③p的后继指针指向s

 

2.当插入链表的非末尾时

①s的后继指针指向p的后继指针

②p的后继结点的前驱指针指向s

③s的前驱指针指向p

④p的后继指针指向s

 

四、双链表的删除

//删除p结点的后继结点
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;
}

思路:

①找到p的后继结点q,DNode *q = p->next

②p的后继指针指向q的后继指针, p->next = q->next

③q的后继结点的前驱指针指向p, q->next->prior = p

④释放结点q

 

五、双链表的遍历

//后向遍历
while(p != NULL){
    p = p->next;
}

//前向遍历
while(p != NULL){
    p = p->prior;
}

//前向遍历(跳过头结点)
while(p->prior != NULL){
    p = p->prior;
}

注:双链表不可随机存取,按位查找、按值查找操作都只能用遍历的方式实现,时间复杂度O(n)

 

你可能感兴趣的:(考研数据结构)