标签:lang number 连接 text nes for ted sed format
Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤10?5??) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address
is the position of the node, Data
is an integer, and Next
is the position of the next node.
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
需要注意的地方
1.已知给定元素个数为n, 但是链表中的元素不一定是n个, 可能有无效元素, 所以需要手动整理计算元素个数 以指针p!=-1;p中存的是下一跳地址 int countList(){}
2.翻转链表的时候, 要保存新产生的子链表头和表尾 , 翻转前的第一个元素是新链的表尾,最后一个元素是新链的表头,
怎么判定谁是子链最后一个元素呢, pre cur next分别指向 前一个元素 当前待翻转的元素 下一个元素
子链翻转之前 pre指向子链第一个元素 因此pre的地址就是新子链的表尾地址
k个元素的子链 需要将后面k-1个元素的下一跳地址指向前k-1个元素, 因此进行了k-1次翻转 经过k-1次翻转后 pre的地址已经来到了 0+k-1 的位置 ,恰好是原子链的最后一个元素,也就是新的子链表头元素
因此 在翻转之前将pre 推入tails数组 , 作为第i个子链的表尾, 翻转之后将pre推入heads数组, 作为第i个子链的表头
3.子链全部翻转后,需要链接各子链
因为已经把各子链的新尾结点和头结点都推入了数组
头结点数组中第一个元素就是新表头的地址
尾结点数组中的第一个就是新的已经翻转的第一个子链的尾部
需要把第i个子链的尾部连接到第i+1个子链的头部
既 list[tail[i]].next=heads[i+1];
4.最后处理链表尾结点的next
如果还有剩余的元素那么把翻转子链的表尾元素next指向下一个子链的头地址即可
此时 cur中存的就是剩余元素的表头, 如果没有后续元素 cur中存的是最后一个元素的表尾 即 -1
list[tails.back()].next=cur;
#include <iostream> #include <vector> #include <map> using namespace std; class node{ public: int data; int next; node()=default; node(int d,int n):data{d},next{n}{}; }; void init(int n,map<int,node> &list){ int addr,data,next; for(int i=0;i<n;i++){ scanf("%d %d %d",&addr,&data,&next);// addr >> data >> next; list[addr]=node{data,next}; } } int countList(map<int,node> &list,int head){ int count{0}; int p=head; while(p!=-1){ count++; p=list[p].next; } return count; } int reverseLinkList(map<int,node> &list,int head,int n,int k){ //三指针分别指向前一个pre 当前需要翻转的元素cur 下一个元素next int turns=n/k,remain=n%k,pre,cur,next; vector<int> heads; vector<int> tails; pre=head; while(turns){ cur=list[pre].next; next=list[cur].next; tails.push_back(pre); //将pre的值赋给temptail,pre存的是第一个结点的地址 待翻转子链的头部 变成新子链的尾部 for(int i=0;i<k-1;i++){//只需要翻转后k-1个元素 //next暂存原链表下一跳地址 list[cur].next=pre;//待翻转元素的下一跳地址指向前一个元素 pre=cur;//前一个元素后移 cur=next;//当前元素后移 next=list[next].next; } heads.push_back(pre);//翻转后的子链头部 turns--;//完成一轮子链翻转后 轮数减一 //下一个子链的表头暂时不变 向前跳过一个位置 pre=cur; } //这样 就有 turns个子链的k个元素被翻转了过来 //接下来需要链接各个子链,因为已经把各子链的新尾结点和头结点都推入了数组 //头结点数组中第一个元素就是新表头的地址 //尾结点数组中的第一个就是新的已经翻转的第一个子链的尾部 //需要把第i个子链的尾部连接到第i+1个子链的头部 //既 list[tail[i]].next=heads[i+1]; for(int i=0;i<heads.size()-1;i++){ list[tails[i]].next=heads[i+1];//子链尾元素的next指向下一个子链的表头地址 } //如果还有剩余的元素那么把翻转子链的表尾元素next指向剩余元素即可,此时 cur中存的就是剩余元素的表头,如果没有后续元素 cur中存的是最后一个元素的表尾 即 -1 list[tails.back()].next=cur; return heads.front(); } void printfList(map<int,node>&list,int head){ int p=head; while(p!=-1){ printf("%05d %d ",p,list[p].data); if(list[p].next!=-1){ printf("%05d\n",list[p].next); }else{ printf("%d\n",list[p].next); } p=list[p].next; } } int main(){ int phead,n,k,newhead; map<int,node> list; cin >> phead >> n >> k; init(n,list); n=countList(list,phead); newhead=reverseLinkList(list, phead, n, k); printfList(list,newhead); return 0; }
数据结构 02-线性结构3 Reversing Linked List (25 分)
标签:lang number 连接 text nes for ted sed format
原文地址:https://www.cnblogs.com/ichiha/p/14775042.html