每日一题——设计双向链表

简介: 每日一题——设计双向链表

设计双向链表

题目链接

要求

题目要我们实现有关双向链表的基本操作,即以下几个函数(与设计单链表相比,由于多了一个指向前一个节点的指针,因此链接两节点的操作要更加复杂,读者可以通过画图进行理解,事半功倍):

MyLinkedList* myLinkedListCreate()    //创建双向链表
int myLinkedListGet(MyLinkedList* obj, int index)   //得到下标为index的节点的值,如果index无效则返回-1
void myLinkedListAddAtHead(MyLinkedList* obj, int val)    //链表头插
void myLinkedListAddAtTail(MyLinkedList* obj, int val)    //链表尾插
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val)    //在下标index处插入值为val的节点,如果index等于链表长度,则相当于尾插
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index)  //删除下标为index的节点,如果index无效,则不操作
void myLinkedListFree(MyLinkedList* obj)    //销毁链表

解析函数形参

同昨天的题目一样,设计单链表,题目所给函数传递的是一级指针,因此我们就要使用带哨兵位的双向链表

实现代码

typedef struct List {
    struct List *next;
    struct List *prev;
    int val;
} MyLinkedList;
//创建双向链表
MyLinkedList* myLinkedListCreate() {
    MyLinkedList *obj = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    obj->prev = obj->next = NULL; //令哨兵位的prev和next指针都初始化为空
    return obj;
}
//返回下标为index的节点的数据,若index无效,则返回-1
int myLinkedListGet(MyLinkedList* obj, int index) {
    int count = 0;
    MyLinkedList *cur = obj->next;  //obj不存储有效数据,因此从next开始计数
    while(cur)
    {
        if(count == index)
            return cur->val;
        cur = cur->next;
        count++;
    }
    return -1;
}
//头插
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
    //创建新节点
    MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    newHead->val = val;
    //如果链表为空
    if(obj->next == NULL)
    {
        //直接将新节点接到哨兵位obj后
        obj->next = newHead;
        newHead->next = NULL;
        newHead->prev = obj;
    }
    //如果链表不为空
    else
    {
        //将新节点嵌入obj和第一个节点之间
        obj->next->prev = newHead;
        newHead->next = obj->next;
        newHead->prev = obj;
        obj->next = newHead;
    }
}
//尾插
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
    //创建新节点
    MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    newHead->val = val;
    //找到链表的尾
    MyLinkedList *cur = obj;
    while(cur->next)
        cur = cur->next;
    //使新节点成为链表的尾
    newHead->prev = cur;
    cur->next = newHead;
    newHead->next = NULL;
}
//在下标为index插入节点
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
    //如果index为0,直接头插
    if(index == 0)
    {
        myLinkedListAddAtHead(obj,val);
        return;
    }
    //创建新节点
    MyLinkedList *newHead = (MyLinkedList *)malloc(sizeof(MyLinkedList));
    newHead->val = val;
    MyLinkedList *cur = obj->next;  //obj不存储有效数据,因此从next开始计数
    int count = 0;
    while(cur)
    {
        if(count == index)
        {
            //实现插入
            cur->prev->next = newHead;
            newHead->prev = cur->prev;
            newHead->next = cur;
            cur->prev = newHead;
        }
        cur = cur->next;
        count++;
    }
    //如果index等于链表长度,则直接尾插
    if(count == index && cur == NULL)
    {
        myLinkedListAddAtTail(obj,val);
        return;
    }
}
//删除下标为index的节点,若index无效,则不操作
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
    int count = 0;
    MyLinkedList *cur = obj->next;  //obj不存储有效数据,因此从next开始计数
    while(cur)
    {
        if(count == index)
        {
            //实现删除
            cur->prev->next = cur->next;
            //如果cur的下一个节点为空,那么就不需要将cur下一个节点的prev指针指向cur前一个节点的操作(因为NULL没有prev)
            if(cur->next)
                cur->next->prev = cur->prev;
            free(cur);
            return;
        }
        count++;
        cur = cur->next;
    }
    return;
}
//销毁链表
void myLinkedListFree(MyLinkedList* obj) {
    MyLinkedList *cur = obj->next;
    while(cur && cur->next)
    {
        MyLinkedList *temp = cur; //保存cur节点,便于销毁
        //重新链接链表
        cur->next->prev = cur->prev;
        cur->prev->next = cur->next;
        cur = cur->next;
        free(temp);
    }
    free(cur);  //销毁最后一个有效节点
    obj->next = NULL; //将哨兵位的next指针置空
}


相关文章
|
存储 人工智能
【手撕数据结构】(三)顺序表和链表
【手撕数据结构】(三)顺序表和链表
140 5
|
存储 算法
数据结构与算法之《带头双向循环链表》详解
数据结构与算法之《带头双向循环链表》详解
75 0
|
7月前
|
存储 算法
数据结构与算法⑦(第二章收尾)带头双向循环链表的实现(上)
数据结构与算法⑦(第二章收尾)带头双向循环链表的实现
45 0
|
7月前
|
存储 缓存 算法
数据结构与算法⑦(第二章收尾)带头双向循环链表的实现(下)
数据结构与算法⑦(第二章收尾)带头双向循环链表的实现
38 0
|
7月前
|
算法 Sentinel
【数据结构算法(二)】链表总结
【数据结构算法(二)】链表总结
|
存储
【数据结构】手撕单链表
【数据结构】手撕单链表
|
存储
【数据结构】手撕双向链表
【数据结构】手撕双向链表
|
存储 C语言
【数据结构】手撕顺序表
【数据结构】手撕顺序表
|
存储 算法
数据结构与算法之六 双向链表和循环链表
数据结构与算法之六 双向链表和循环链表
45 0
|
存储 测试技术 C语言
【数据结构】带你轻松拿捏顺序表(内附源码)
【数据结构】带你轻松拿捏顺序表(内附源码)
100 0