6.2 链表 (UVa 11988, 12657)

掌握链表的删除,插入,遍历。可以用数组来构造链表。

例题 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;
}
原文地址:https://www.cnblogs.com/lighter-blog/p/6118898.html