OJ2219左移右移(链表)——蓝桥杯2022年国赛

代码为(双向链表):

#include <bits/stdc++.h>
using namespace std;
struct link {
    int data;
    link* prev;
    link* next;
};
int main()
{
    int n, m; cin >> n >> m;
link* l = new link();  // 创建头节点,不存储实际数据,仅作为起始点
link* tail = l;        // 尾指针初始指向头节点
unordered_map<int, link*> h;  // 哈希表,用于快速查找任何节点
for (int i = 1; i <= n; i++) {
    link* p = new link();
    p->data = i;
    p->next = nullptr;
    p->prev = tail;
    tail->next = p;
    tail = p;
    h[i] = p;  // 存储指针到哈希表,以便通过数据值快速定位节点
}
for (int i = 0; i < m; i++) {
    char c; int a; cin >> c >> a;
    link* tar = h[a];  // 从哈希表中直接获取目标节点
    if (c == 'L') {  // 左移操作
        if (tar->prev->data != 0) {  // 如果已经是第一个实际节点,则不操作
            if (tar->next != nullptr) {  // 如果不是最后一个节点
                tar->next->prev = tar->prev;
            } else {
                tail = tar->prev;  // 更新尾指针
            }
            tar->prev->next = tar->next;  // 从当前位置移除节点

            // 将节点移至头部
            tar->next = l->next;
            l->next->prev = tar;
            tar->prev = l;
            l->next = tar;
        }
    } else {  // 右移操作
        if (tar->next != nullptr) {  // 如果不是最后一个节点
            tar->prev->next = tar->next;
            tar->next->prev = tar->prev;  // 从当前位置移除节点
            
            // 将节点移至尾部
            tar->next = nullptr;
            tar->prev = tail;
            tail->next = tar;
            tail = tar;  // 更新尾指针
        }
    }
}
l = l->next;
    while (l) {
        cout << l->data << " ";
        l = l->next;
     }
    return 0;
}

注:

  unordered_map 来实现快速查找节点。

分析:

link* l = new link();  
link* tail = l;       
unordered_map<int, link*> h; 
for (int i = 1; i <= n; i++) {
    link* p = new link();
    p->data = i;
    p->next = nullptr;
    p->prev = tail;
    tail->next = p;
    tail = p;
    h[i] = p;  
}

这一段代码初始化了链表,从头节点开始,逐个添加节点到链表尾部。同时,在哈希表中保存每个值与对应节点的映射,这样可以在 O(1) 时间复杂度内通过节点值找到对应的链表节点。

for (int i = 0; i < m; i++) {
    char c; int a; cin >> c >> a;
    link* tar = h[a];  
    if (c == 'L') { 
        if (tar->prev->data != 0) {  
            if (tar->next != nullptr) {  
                tar->next->prev = tar->prev;
            } else {
                tail = tar->prev;  
            }
            tar->prev->next = tar->next;  
       
            tar->next = l->next;
            l->next->prev = tar;
            tar->prev = l;
            l->next = tar;
        }
    } else {  // 右移操作
        if (tar->next != nullptr) {  
            tar->prev->next = tar->next;
            tar->next->prev = tar->prev;  
            
            // 将节点移至尾部
            tar->next = nullptr;
            tar->prev = tail;
            tail->next = tar;
            tail = tar;  
        }
    }
}

这段代码处理每个移动操作:

  • 左移:将节点移至链表的首部(即头节点的直接后继),确保不是已经在最前面。
  • 右移:将节点移至链表的尾部,确保不是已经在最后面。
l = l->next;
while (l) {
    cout << l->data << " ";
    l = l->next;
}

最后,从头节点的下一个节点开始,遍历链表并输出每个节点的数据,直到链表结束。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值