SDUT数据结构PTA专题(实验二)题解

数据结构与算法A实验二链表

  • 7 - 1 单链表的创建及遍历
  • 7 - 2 两个有序链表序列的合并
  • 7 - 3 单链表的创建,遍历与销毁
  • 7 - 4 程序设计综合实践 1.3
  • 7 - 5 程序设计综合实践 1.4
  • 7 - 6 删除重复字符
  • 7 - 7 约瑟夫环
  • 7 - 8 一元多项式的乘法与加法运算
  • 7 - 9 带头节点的双向循环链表操作
  • 7 - 10 链表去重
  • 7 - 11 单链表就地逆置

7 - 1 单链表的创建及遍历

#include
using namespace std;

struct node{  // 定义节点结构体
    int data;  // 值
    node *next;  // 指向下一个节点的索引
};

node *build(node *head,int n){  // 建立链表
    head=new node;  
    node *tail,*p;
    head->next=NULL;
    tail=head;
    for(int i=1;i<=n;i++){  // 输入链表的值
        p=new node;
        cin>>p->data;
        p->next=tail->next;
        tail->next=p;
        tail=p;
    }
    return head;
}

void show(node *head){   // 输出列表
    node *p=head->next;
    while(p){  // 节点不为空
        if(p->next) cout<<p->data<<" ";  // 最后一个节点输出换行
        else cout<<p->data<<endl;        // 不是最后一个节点输出空格
        p=p->next;       // 指针移动到下一个节点
    }
}

void solve(){
    int n;
    cin>>n;
    node *head=new node;  // 定义链表
    head=build(head,n);    // 建立链表
    show(head);      // 输出链表head
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 2 两个有序链表序列的合并

#include
using namespace std;

struct node{  // 定义节点结构体
    int data;  // 值
    node *next;  // 指向下一个节点的索引
};

node *build(node *head){  // 建立链表
    head=new node;  
    node *tail,*p;
    head->next=NULL;
    tail=head;
    int k;
    while(cin>>k&&k!=-1){  // 输入链表的值
        p=new node;
        p->data=k;
        p->next=tail->next;
        tail->next=p;
        tail=p;
    }
    return head;
}

node *Merge(node *h1,node *h2){  // 合并链表
    node *t1=h1->next,*t2=h2->next;
    node *p,*tail;
    node *head=new node;
    head->next=NULL;
    tail=head;
    while(t1&&t2){
        if(t1->data<t2->data){  // 如果t1值小合并到head中
            p=new node;
            p->data=t1->data;
            p->next=tail->next;
            tail->next=p;
            tail=p;
            t1=t1->next;
        }else{  // 如果t2值小合并到head中
            p=new node;
            p->data=t2->data;
            p->next=tail->next;
            tail->next=p;
            tail=p;
            t2=t2->next;
        }
    }
    if(t1) tail->next=t1;  // 如果h1链表有剩余 把剩余的放入
    if(t2) tail->next=t2;  // 如果h2链表有剩余 把剩余的放入
    return head;
}

void show(node *head){   // 输出列表
    node *p=head->next;
    while(p){  // 节点不为空
        if(p->next) cout<<p->data<<" ";  // 最后一个节点输出换行
        else cout<<p->data<<endl;        // 不是最后一个节点输出空格
        p=p->next;       // 指针移动到下一个节点
    }
}

void solve(){
    node *head1=new node;  // 定义链表一
    node *head2=new node;  // 定义链表二
    head1=build(head1);    // 建立链表一
    head2=build(head2);    // 建立链表二
    //show(head1);
    //show(head2);
    node *head=Merge(head1,head2);  // 合并链表一、二
    if(head->next) show(head);      // 如果链表不为空 输出链表head
    else cout<<"NULL"<<endl;        // 如果链表为空   输出 NULL
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 3 单链表的创建,遍历与销毁

#include
using namespace std;

struct node{  // 定义节点结构体
    int data;  // 值
    node *next;  // 指向下一个节点的索引
};

node *build(node *head){  // 逆序建立链表
    head=new node;  
    node *tail,*p;
    head->next=NULL;
    tail=head;
    int k;
    while(cin>>k&&k!=-1){  // 输入链表的值
        p=new node;
        p->data=k;
        p->next=head->next;
        head->next=p;
    }
    return head;
}

void show(node *head){   // 输出列表
    node *p=head->next;
    while(p){  // 节点不为空
        cout<<p->data<<" ";  // 输出节点
        p=p->next;       // 指针移动到下一个节点
    }
}

void solve(){
    node *head=new node;  // 定义链表
    head=build(head);    // 建立链表
    show(head);      // 输出链表head
    free(head);      // 释放head
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 4 程序设计综合实践 1.3

法一:链表

#include
#define ll long long
const int N = 1e7 + 10;
using namespace std;

int tot;   // 记录数据个数
int a[N];  // 记录数据
struct node{  // 定义节点结构体
    int data;
    node *next;
};

node *head1,*head2;  // 定义链表

void Reverse(node *head){  // 链表逆置
    node *p,*s;
    p=head->next;
    head->next=NULL;
    while(p){
        s=p;
        p=p->next;
        s->next=head->next;
        head->next=s;
    }
}

void show(node *head){  // 输出链表
    node *p=head->next;
    if(!p) cout<<endl;  // 如果是空链表输出换行 !!
    while(p){
        if(p->next) cout<<p->data<<"->";
        else cout<<p->data<<endl;;
        p=p->next;
    }
}

void add(node *head,int x){  // 插入节点函数
    node *tail=head;
    node *q=head->next;
    node *p;
    if(!q){  // 如果当前链表没有节点
        p=new node;
        p->data=x;
        p->next=head->next;
        head->next=p;
        }else{  // 如果当前链表有节点
        bool tag=0;
        while(q&&!tag){  // 按序插入节点
            if(x<=q->data){
                tag=1;
                p=new node;
                p->data=x;
                p->next=tail->next;
                tail->next=p;
                break;
            }else{
                q=q->next;
                tail=tail->next;
            }
        }
        if(!tag){  // 如果是最大的 插入到最后
            p=new node;
            p->data=x;
            p->next=tail->next;
            tail->next=p;
        }
    }
}

void build(node *head1,node *head2){  // 构建链表
    head1=new node; head1->next=NULL;
    head2=new node; head2->next=NULL;
    node *p;
    for(int i=1;i<=tot;i++){
        if(a[i]>0) add(head1,a[i]);  // 如果是正整数
        else if(a[i]<0) add(head2,a[i]);   // 如果负整数
    }
    show(head1); show(head2);  // 输出链表
    Reverse(head1);Reverse(head2);  // 链表逆置
    show(head1); show(head2);  // 输出逆置链表
}

void solve(){
    string s;
    getline(cin,s);
    stringstream ss(s);
    while(ss>>s){ // 读入元素并存储
        int num=0;
        if(s[0]=='-'){
            for(int i=1;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=-num;
        }else{
            for(int i=0;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=num;
        }
    }
    head1=new node;head1->next=NULL;
    head2=new node;head2->next=NULL;
    build(head1,head2);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

法二:数组

#include 
#include 
#include
#define ll long long
#define mem(a,b) memset(a,b,sizeof a)
#define ull unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) x&(-x)
#define PII pair<int,int>
#define x first
#define y second
#define PLL pair<ll,ll>
#define PI acos(-1)
#define pb push_back
#define eb emplace_back
const double eps = 1e-6;
const int mod = 998244353;
const int MOD = 1e9 + 7;
const int N = 2e5 + 10;
const int M = 111;
int dx[]={-1, 0, 1, 0};
int dy[]={0, 1, 0, -1};
using namespace std;

int a[N],tot;

void show(int l,int r){
    if(!l||!r){  //  如果是空输出换行
        cout<<endl;
        return ;
    }
    if(l<=r){
        for(int i=l;i<=r;i++){
            if(i!=l) cout<<"->";
            cout<<a[i];
        }
        cout<<endl;
    }else{
        for(int i=l;i>=r;i--){
            if(i!=l) cout<<"->";
            cout<<a[i];
        }
        cout<<endl;
    }
}

inline void solve(){
    string s;
    getline(cin,s);
    stringstream ss(s);
    while(ss>>s){  // 将数据存入数组
        int num=0;
        if(s[0]=='-'){
            for(int i=1;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=-num;
        }else{
            for(int i=0;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=num;
        }
    }
    sort(a+1,a+1+tot);  // 排序
    int pos=0;
    for(int i=1;i<=tot;i++){   // 找到第一个正数位置
        if(a[i]>0){
            pos=i;
            break;
        }
    }
    //  输出结果
    show(pos,tot);
    show(1,pos-1);
    show(tot,pos);
    show(pos-1,1);
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7 - 5 程序设计综合实践 1.4

#include
#define ll long long
const int N = 1e7 + 10;
using namespace std;

int tot;   // 记录数据个数
int a[N];  // 记录数据
struct node{  // 定义节点结构体
    int data;
    node *next;
};

node *head,*head1,*head2;  // 定义链表

void show(node *head){  // 输出链表
    node *p=head->next;
    if(!p) cout<<endl;  // 如果是空链表输出换行 !!
    while(p){
        if(p->next) cout<<p->data<<"->";
        else cout<<p->data<<endl;;
        p=p->next;
    }
}

void add(node *head,int x){  // 插入节点函数
    node *tail=head;
    node *q=head->next;
    node *p;
    if(!q){  // 如果当前链表没有节点
        p=new node;
        p->data=x;
        p->next=head->next;
        head->next=p;
        }else{  // 如果当前链表有节点
        bool tag=0;
        while(q&&!tag){  // 按序插入节点
            if(x<=q->data){
                tag=1;
                p=new node;
                p->data=x;
                p->next=tail->next;
                tail->next=p;
                break;
            }else{
                q=q->next;
                tail=tail->next;
            }
        }
        if(!tag){  // 如果是最大的 插入到最后
            p=new node;
            p->data=x;
            p->next=tail->next;
            tail->next=p;
        }
    }
}

void build(node *head,node *head1,node *head2){  // 构建链表
    head1=new node; head1->next=NULL;
    head2=new node; head2->next=NULL;
    node *p;
    for(int i=1;i<=tot;i++){
        add(head,a[i]);  // 插入总链表
        if(a[i]&1) add(head1,a[i]);  // 如果是奇数
        else add(head2,a[i]);   // 如果是偶数
    }
    show(head);show(head1); show(head2);  // 输出链表
}

void solve(){
    string s;
    getline(cin,s);
    stringstream ss(s);
    while(ss>>s){ // 读入元素并存储
        int num=0;
        if(s[0]=='-'){
            for(int i=1;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=-num;
        }else{
            for(int i=0;i<s.size();i++){
                num=num*10+s[i]-'0';
            }
            a[++tot]=num;
        }
    }
    head=new node;head->next=NULL;
    head1=new node;head1->next=NULL;
    head2=new node;head2->next=NULL;
    build(head,head1,head2);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 6 删除重复字符

坑点: 有空格!

#include
using namespace std;

set<char>st;

void solve(){
    string s;
    getline(cin,s);
    for(int i=0;i<s.size();i++) st.insert(s[i]);
    for(auto i:st) cout<<i; 
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 7 约瑟夫环

#include
#define eb emplace_back
using namespace std;

int n;

struct node{  // 定义节点结构体
    int data;  // 值
    node *next;  // 指向下一个节点的索引
};

vector<int>ord;

node *build(node *head){  // 逆序建立链表
    head=new node;  
    node *tail,*p;
    head->next=NULL;
    head->data=1;  // 建立第一个节点
    tail=head;
    for(int i=2;i<=n;i++){  // 输入链表的值  顺序建链表
        p=new node;
        p->data=i;
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    tail->next=head;  // 尾节点和头节点链接 形成循环链表
    return head;
}

void Joseph(node *head,int p){  // 按照要求退出
    node *tail=head;
    for(int i=1;i<n;i++) tail=tail->next; // 找到头节点的前一个节点 便于p=1时的删除
    node *q=head;
    int tot=n;
    int cnt=1;
    while(tot>1){  // 删点过程
        if(cnt==p){   // 如果报数为p 则删除
            ord.eb(q->data);  // 存入答案
            tot--;         // 节点数量减少1
            cnt=1;         // 从头报数
            tail->next=q->next;  // 删点
            q=tail->next;
        }else{  // 没有报到p 则后移
            q=q->next;
            tail=tail->next;
            cnt++;
        }
    }
    ord.eb(q->data); // 放入最后一个节点
}

void solve(){
    int p;
    cin>>n>>p;
    node *head=new node;  // 定义链表
    head=build(head);    // 建立链表
    Joseph(head,p);    //  按照要求删点
    for(int i=0;i<ord.size();i++){  // 输出退出顺序
        if(i) cout<<" ";
        cout<<ord[i];
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}


7 - 8 一元多项式的乘法与加法运算

#include
#define ll long long
#define eb emplace_back
#define x first
#define y second
const int N = 1e7 + 10;
using namespace std;

map<ll,ll>ind;  // 记录加法系数
vector<ll>res;  // 记录加法答案
map<ll,ll>ap,bp,cp;  // ap 记录第一个方程 bp 表示第二个方程 cp 表示乘法结果
vector<ll>vp;   // 记录乘法答案

void show(map<ll,ll>Index,vector<ll>Res){  // 输出函数
    for(auto i:Index){  // 遍历指数 去除系数为零的指数
        if(i.y){
            Res.eb(i.x);
            Res.eb(i.y);
        }
    }
    if(Res.size()){  // 如果不是零多项式 倒序输出
        for(int i=Res.size()-1;i>=0;i--){
            if(i!=Res.size()-1) cout<<" ";
            cout<<Res[i];
        }
        cout<<endl;
    }else cout<<"0 0"<<endl;  // 如果是零多项式 输出 0 0
}

void solve(){
    int n;
    cin>>n;
    int a,b;
    for(int i=1;i<=n;i++){ // 输入第一个表达式
        cin>>a>>b;
        ind[b]+=a;  // 对应指数位置加上系数值
        ap[b]+=a;
    }
    cin>>n;
    for(int i=1;i<=n;i++){  // 输入第二个表达式
        cin>>a>>b;
        ind[b]+=a;
        bp[b]+=a;
    }
    for(auto i:ap){ //  乘法运算
        for(auto j:bp){
            cp[i.x+j.x]+=i.y*j.y;
        }
    }
    show(cp,vp);    // 输出乘法结果
    show(ind,res);  // 输出加法结果
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7 - 9 带头节点的双向循环链表操作

双向链表: 注意每个节点的pre和next链接

#include
#define ll long long
const int N = 1e7 + 10;
using namespace std;

int tot;   // 记录数据个数
int a[N];  // 记录数据
struct node{  // 定义节点结构体
    int data;
    node *pre;
    node *next;
};

void show(node *head){  // 输出链表
    node *p=head->next;
    while(p){
        if(p->next) cout<<p->data<<" ";
        else cout<<p->data<<endl;;
        p=p->next;
    }
}

void reshow(node *tail){  // 逆序输出链表
    node *p=tail;
    while(p->pre){
        if(p->pre->pre) cout<<p->data<<" ";
        else cout<<p->data<<endl;;
        p=p->pre;
    }
}

void build(node *head){  // 构建链表
    head=new node; 
    head->pre=NULL;
    head->next=NULL;
    node *p;
    node *tail=head;
    node *q=head->next;
    for(int i=1;i<=tot;i++){  // 插入节点
        q=head->next;
        int x=a[i];
        if(!q){  // 如果当前链表没有节点
            p=new node;
            p->data=x;
            p->pre=head;
            p->next=head->next;
            head->next=p;
            tail=p;
        }else{  // 如果当前链表有节点
            if(i&1){
                p=new node;
                p->data=x;
                p->pre=head;
                p->next=head->next;
                p->next->pre=p;
                head->next=p;
            }else{
                p=new node;
                p->data=x;
                p->next=NULL;
                p->pre=tail;
                tail->next=p;
                tail=p;
            }
        }
    }
    show(head);  // 输出链表
    reshow(tail);  // 输出逆置链表
}

void solve(){
    int x;
    while(cin>>x&&x!=-1) a[++tot]=x;
    node *head=new node;
    head->next=NULL;
    build(head);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

单向链表:

#include
#define ll long long
const int N = 1e7 + 10;
using namespace std;

int tot;   // 记录数据个数
int a[N];  // 记录数据
struct node{  // 定义节点结构体
    int data;
    node *pre;
    node *next;
};

void Reverse(node *head){  // 链表逆置
    node *p,*s;
    p=head->next;
    head->next=NULL;
    while(p){
        s=p;
        p=p->next;
        s->next=head->next;
        head->next=s;
    }
}

void show(node *head){  // 输出链表
    node *p=head->next;
    while(p){
        if(p->next) cout<<p->data<<" ";
        else cout<<p->data<<endl;;
        p=p->next;
    }
}

void build(node *head){  // 构建链表
    head=new node; 
    head->next=NULL;
    node *p;
    node *tail=head;
    node *t=head;
    node *q=head->next;
    for(int i=1;i<=tot;i++){  // 插入节点
        q=head->next;
        int x=a[i];
        if(!q){  // 如果当前链表没有节点
            p=new node;
            p->data=x;
            p->next=head->next;
            head->next=p;
            t=p;
        }else{  // 如果当前链表有节点
            if(i&1){
                p=new node;
                p->data=x;
                p->next=head->next;
                head->next=p;
            }else{
                p=new node;
                p->data=x;
                p->next=NULL;
                t->next=p;
                t=p;
            }
        }
    }
    show(head);  // 输出链表
    Reverse(head);  // 链表逆置
    show(head);  // 输出逆置链表
}

void solve(){
    int x;
    while(cin>>x&&x!=-1) a[++tot]=x;
    node *head=new node;
    head->next=NULL;
    build(head);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

7 - 10 链表去重

#include 
#include
#include
#include
#include
#define ll long long
#define INF 0x3f3f3f3f
const int N = 1e5 + 10;
using namespace std;

struct node{
    int add;
    int key;
    int next;
    int num;
} dp[N];

bool vis[N];
bool cmp(node x,node y){
    return x.num<y.num;
}


int main(){
    ios::sync_with_stdio(0);
    int head;
    int n;
    cin>>head>>n;
    int i;
    int k1=0;
    int k2=0;
    for(i=0; i<N; i++)dp[i].num=2*N;
    int k;
    for(i=0; i<n; i++){
        cin>>k;
        cin>>dp[k].key>>dp[k].next;
        dp[k].add=k;
    }
    for(i=head; i!=-1; i=dp[i].next){
        if(!vis[abs(dp[i].key)]){
            vis[abs(dp[i].key)]=1;
            dp[i].num=k1;
            k1++;
        }else{
            dp[i].num=N+k2;
            k2++;
        }
    }
    sort(dp,dp+N,cmp);
    int cnt=k1+k2;
    for(i=0; i<cnt; i++){
        if(i!=k1-1&&i!=cnt-1) printf("%05d %d %05d\n",dp[i].add,dp[i].key,dp[i+1].add);
        else printf("%05d %d -1\n",dp[i].add,dp[i].key);
    }
    return 0;
}

7 - 11 单链表就地逆置

#include
using namespace std;

struct node{  // 定义节点结构体
    int data;  // 值
    node *next;  // 指向下一个节点的索引
};

node *build(node *head){  // 逆序建立链表
    head=new node;  
    node *tail,*p;
    head->next=NULL;
    tail=head;
    int k;
    while(cin>>k&&k!=-1){  // 输入链表的值
        p=new node;
        p->data=k;
        p->next=head->next;
        head->next=p;
    }
    return head;
}

void show(node *head){   // 输出列表
    node *p=head->next;
    while(p){  // 节点不为空
        if(p->next) cout<<p->data<<" ";  // 最后一个节点输出换行
        else cout<<p->data<<endl;        // 不是最后一个节点输出空格
        p=p->next;       // 指针移动到下一个节点
    }
}

void solve(){
    node *head=new node;  // 定义链表
    head=build(head);    // 建立链表
    show(head);      // 输出链表head
    free(head);      // 释放head
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}


你可能感兴趣的:(PTA,题解,链表,数据结构,链表,算法)