掌握链表的删除,插入,遍历。可以用数组来构造链表。
例题 6-4
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=838&page=show_problem&problem=3139
思路:以单个字符为结点,构造链表,遇到 ' [ ' 字符时,接下来的输入就在开头插入,遇到 ' ] ' 字符时,接下来的输入就在结尾插入。
代码:
/* Broken Keyboard (UVa 11988) */ #include<iostream> #include<cstring> //#define LOCAL using namespace std; int main(){ #ifdef LOCAL freopen("input.txt","r",stdin); //freopen("output.txt","w",stdout); #endif int cur,last; //cur为当前指针指向的字符,last为[之前的最后一个字符 char str[100005]; //存放字符串 int next[100005]; //下一个字符的下标,形成链表,0为头结点 while(scanf("%s",str+1)!=EOF){ int len=strlen(str+1); //注意是str+1 cur=0; last=0; memset(next,0,sizeof(next)); for(int i=1;i<=len;i++){ if(str[i]=='[') //如果遇到 '[' ,就将当前指针指向头指针 cur=0; else if(str[i]==']') //如果遇到 ']' ,就将当前指针指向上一个'['前的最后一个字符(最外层的'['),即链表中最后一个字符 cur=last; else{ //cout<<i<<endl; //即将第i个字符插入当前指向的字符的后面 next[i]=next[cur]; next[cur]=i; //更新cur和last if(cur==last) last=i; cur=i; } } //输出链表 for(int i=0;next[i]!=0;){ i=next[i]; printf("%c",str[i]); } cout<<endl; memset(str,0,sizeof(str)); } return 0; }
例题 6-5
题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=838&page=show_problem&problem=4395
思路:使用双向链表,灵活运用 link(a, b) 函数,将 x 移动到 y 的左边时,就 link(x_left, x_right), link(y_left, x), link(x, y), 注意,当反转链表时,相对方向也要改变,还要注意交换相邻的两个节点时的情况。
代码:
/* Boxes in a Line (UVa 12657) */ #include <iostream> #include <cstring> using namespace std; const int maxn = 100005; int Left[maxn], Right[maxn]; int *front = Left, *back = Right; //前、后。 int n, m; void init(); void link(int a, int b); //连接 a 点和 b 点,a 在 b 之“前” void output(); //调试,输出当前序列 int main(){ //freopen("input.txt", "r", stdin); int kase = 0; while(cin >> n >> m){ init(); for(int i=0; i<m; i++){ int x, y, z; cin >> x; if(x == 4){ swap(front, back); continue; } cin >> y >> z; if(x == 1){ link(front[y], back[y]); link(front[z], y); link(y, z); } if(x == 2){ link(front[y], back[y]); link(y, back[z]); link(z, y); } if(x == 3){ int front_y = front[y], back_y = back[y], front_z = front[z], back_z = back[z]; if(front[y] == z){ //注意相邻情况 link(z, back_y); link(front_z, y); link(y, z); }else if(front[z] == y){ link(y, back_z); link(front_y, z); link(z, y); }else{ link(front_y, z); link(z, back_y); link(front_z, y); link(y, back_z); } } } int t = 0; long long sum = 0; for(int i=1; i<=n; i++){ t = back[t]; if(i%2 == 1) sum += t; } //output(); cout << "Case " << ++kase << ": "<< sum << endl; } } void init(){ front = Left; back = Right; memset(Left, 0, sizeof(Left)); memset(Right, 0, sizeof(Right)); for(int i=1; i<n; i++){ link(i, i+1); } link(0, 1); link(n, 0); } void link(int a, int b){ back[a] = b; front[b] = a; } void output(){ int t = 0; for(int i=0; i<n; i++){ t = back[t]; cout << t << " "; } cout << endl; }