7-11 重排链表 (25 分)

#include "bits/stdc++.h"
using namespace std;
const int N = 1e5+5;
vector<int>ans;
deque<int>d;
int head,n,x;
struct node{
    int l,val,r;
}arr[N];
int main()
{
    cin >> head >> n;
    for(int i=0 ;i<n;i++){
        cin >> x;
        cin >> arr[x].val >> arr[x].r;
        arr[x].l = x;
    }
    while (head!=-1){
        d.push_back(arr[head].l);
        head=arr[head].r;
    }
    while (!d.empty()){
        ans.push_back(d.back());
        d.pop_back();
        if(d.empty()) break;
        ans.push_back(d.front());
        d.pop_front();
    }
    int len = ans.size();
    for(int i=0;i<len ; i++){
        if(i == len-1) printf("%05d %d -1\n",ans[i],arr[ans[i]].val);
        else printf("%05d %d %05d\n",ans[i],arr[ans[i]].val,ans[i+1]);
    }


    return 0;
}

### 实现7-3重排链表 要实现7-3重排链表的功能,可以按照以下逻辑完成。此问题的核心是对链表的操作以及如何将原链表中的节点按特定顺序重新排列。 #### 1. 数据结构定义 首先需要定义两种数据结构来存储和操作链表的信息: ```c typedef struct Node { int no; // 地址编号 int data; // 节点保存的数据 int non; // 下一个地址编号 struct Node* next; struct Node* front; } Node; typedef struct { int data[100001]; // 存储每个地址对应的数据 int next[100001]; // 存储每个地址对应的下一个地址 int first; // 表头地址 } SqList; ``` 上述 `Node` 和 `SqList` 的定义别用于表示单个节点和整个线性表的存储方式[^1]。 --- #### 2. 构建原始链表 根据输入构建初始链表时,可以通过读取每条记录并将其存入数组形式的线性表中。具体方法如下: 假设输入样例如下: ``` 68237 6 00100 00100 1 99999 99999 5 12309 12309 2 00000 00000 4 33218 33218 3 -1 ``` 对于每一行输入,解析其三个字段别为当前节点的地址 (`Address`)、数据值 (`Data`) 和指向下一节点的地址 (`Next Address`)。这些信息可以直接填充到 `SqList` 中的相应位置[^4]。 --- #### 3. 链表重组算法 为了实现链表的重新排列,需遵循以下原则: 从首尾交替取出节点,并依次连接形成新的链表。以下是具体的实现过程: ##### (1)初始化指针变量 创建两个辅助指针 `pHead` 和 `pTail` 来追踪新链表的头部和尾部。同时维护两个索引来访问原链表的起始部和结束部。 ##### (2)遍历原链表 利用双端队列的思想,每次从原链表的一端提取一个节点加入新链表中。当剩余未处理的节点数量大于等于2时继续执行循环;否则停止。 ##### (3)更新链接关系 在每一次迭代过程中调整被选中节点与其前后邻居之间的关联关系以确保最终形成的是一条完整的连续路径[^3]。 --- #### 4. 完整代码示例 下面提供了一个基于C语言的具体实现方案: ```c #include <stdio.h> #define MAXN 100001 // 结构体声明同上... void build(SqList *list, int n) { char addrStr[6]; int address, data, nextAddr; list->first = -1; // 初始化第一个有效节点为空 while(n--) { scanf("%s %d %d", addrStr, &data, &nextAddr); sscanf(addrStr, "%d", &address); // 将字符串转换成整型 list->data[address] = data; list->next[address] = nextAddr; if(list->first == -1 && nextAddr != -1){ list->first = address; // 记录首个有效的节点作为起点 } } } void rearrange(SqList *list) { int p = list->first, q, prevP=-1, count=0; // 统计总长度 for(q=p; q!=-1; q=list->next[q]) ++count; int mid = (count / 2), i=mid; q = p; // 找到最后一半的第一个元素的位置 while(i--){ prevP = q; q = list->next[q]; } // 断开两半之间原有的联系 if(prevP >=0 ) list->next[prevP]=-1 ; // 开始交叉拼接 while(p != -1 || q != -1 ){ printf("%05d %d ", p>=0?p:q , list->data[p>=0 ? p : q]); if(p >=0 ){ p = list->next[p]; }else{ break; } if(q >=0 ){ printf("%d\n%05d %d ", list->next[q], q, list->data[q]); q = list->next[q]; }else{ break; } } } ``` --- #### 输出说明 以上代码会输出经过重新排序后的链表内容,满足题目要求的形式化表达。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值