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

每日一题

设计双向链表

题目链接

要求

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

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指针置空
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以帮你设计双向链表实现大整数四则运算。 首先,我们可以定义一个节点结构体,有三个成员变量:前驱指针 prev、后继指针 next、节点值 val。其中,节点值 val 可以用一个 int 数组存储,每个 int 存储一位数字。 ```c++ struct Node { int val[4]; // 每个 int 存储 4 位数字 Node* prev; Node* next; }; ``` 然后,我们可以定义一个双向链表结构体,有两个指针成员变量:头指针 head 和尾指针 tail。我们可以在双向链表中定义一些基本的操作,如插入节点、删除节点、遍历链表等。 ```c++ struct DoubleLinkedList { Node* head; Node* tail; // 在链表末尾插入节点 void insertNode(Node* node) { if (head == NULL) { head = tail = node; } else { tail->next = node; node->prev = tail; tail = node; } } // 删除链表中的节点 void deleteNode(Node* node) { if (node == head && node == tail) { head = tail = NULL; } else if (node == head) { head = head->next; head->prev = NULL; } else if (node == tail) { tail = tail->prev; tail->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } } // 遍历链表,输出所有节点的值 void traverse() { Node* cur = head; while (cur != NULL) { for (int i = 3; i >= 0; i--) { cout << cur->val[i]; } cur = cur->next; } cout << endl; } }; ``` 有了双向链表的基本操作,我们就可以实现大整数的四则运算了。以下是加法和减法的实现代码。 ```c++ // 大整数加法 void add(DoubleLinkedList& num1, DoubleLinkedList& num2, DoubleLinkedList& sum) { Node* cur1 = num1.head; Node* cur2 = num2.head; int carry = 0; while (cur1 != NULL || cur2 != NULL) { Node* node = new Node(); int val = carry; if (cur1 != NULL) { for (int i = 0; i < 4; i++) { val += cur1->val[i]; } cur1 = cur1->next; } if (cur2 != NULL) { for (int i = 0; i < 4; i++) { val += cur2->val[i]; } cur2 = cur2->next; } carry = val / 10000; val = val % 10000; for (int i = 0; i < 4; i++) { node->val[i] = val % 10; val /= 10; } sum.insertNode(node); } if (carry > 0) { Node* node = new Node(); for (int i = 0; i < 4; i++) { node->val[i] = carry % 10; carry /= 10; } sum.insertNode(node); } } // 大整数减法 void subtract(DoubleLinkedList& num1, DoubleLinkedList& num2, DoubleLinkedList& diff) { Node* cur1 = num1.head; Node* cur2 = num2.head; int borrow = 0; while (cur1 != NULL || cur2 != NULL) { Node* node = new Node(); int val = borrow; if (cur1 != NULL) { for (int i = 0; i < 4; i++) { val += cur1->val[i]; } cur1 = cur1->next; } if (cur2 != NULL) { for (int i = 0; i < 4; i++) { val -= cur2->val[i]; } cur2 = cur2->next; } if (val < 0) { val += 10000; borrow = -1; } else { borrow = 0; } for (int i = 0; i < 4; i++) { node->val[i] = val % 10; val /= 10; } diff.insertNode(node); } // 去除前导零 while (diff.tail != NULL && diff.tail != diff.head && diff.tail->val[3] == 0) { Node* temp = diff.tail; diff.tail = diff.tail->prev; diff.tail->next = NULL; delete temp; } } ``` 以上是双向链表实现大整数四则运算的基本思路和代码实现。当然,这只是一个简单的实现,还有很多可以优化的地方,比如可以用 STL 中的 vector 代替 int 数组来存储节点值,提高代码可读性和易维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Forward♞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值