浅谈链表应用

题面传送门
链表,顾名思义,就是一根链,由许多节点构成,每个节点分为两个部分:数据域和指针域,其中数据域可以包含很多数据,指针域只能包含一个指向对象,不然就成图了。链表可以 O ( 1 ) O(1) O(1)插入和删除数据,但不能随机访问元素。
链表实现就不再乱说了。毕竟是个人都会。主要讲一些链表的应用。
这道题很简单,只要顺着链表找下去,找到第m个点就删掉就好了。
代码实现:

#include<cstdio>
using namespace std;
int n,m,f[100039],head,cnt=1,h[100039];
int main(){
    register int i,j;
    scanf("%d%d",&n,&m);
    for(i=2;i<=n;i++) f[i]=i-1;
    f[1]=n;
    for(i=1;i<n;i++) h[i]=i+1;
    h[n]=1;
    for(i=1;i<n;i++){
        for(j=1;j<=m;j++)cnt=h[cnt];
        f[cnt]=f[f[cnt]];
        h[f[cnt]]=cnt;
    }
    printf("%d",cnt);
}

题面传送门
这道题也不难看出是链表,可是如果用单链表的话,我们来模拟一下:
原来是 1 − > 2 − > 3 − > 4 − > 5 1->2->3->4->5 1>2>3>4>5
第一次插队把 1 1 1插到 2 2 2的后面。
2 − > 1 − > 3 − > 4 − > 5 2->1->3->4->5 2>1>3>4>5
第二次把 2 2 2插到 4 4 4的后面:
1 − > 3 − > 4 − > 2 − > 5 1->3->4->2->5 1>3>4>2>5
第三次把 3 3 3插到 5 5 5的后面:
1 − > 3 1->3 1>3
3 − > 2 − > 5 − > 3 3->2->5->3 3>2>5>3
这就不是链表了,而且也没有我们想要的目的。那么 3 3 3怎么找到 1 1 1前面的那个呢?那就用双向链表呗!
代码实现:

#include<cstdio>
using namespace std;
int n,m,x,y,f[100039],h[100039],head=1;
int main() {
    register int i;
    scanf("%d%d",&n,&m);
    for(i=2; i<=n; i++) f[i]=i-1;
    for(i=1; i<n; i++) h[i]=i+1;
    for(i=1; i<=m; i++) {
        scanf("%d%d",&x,&y);
        if(!f[x]) {
            head=h[x];
            f[h[x]]=0;
            h[x]=0;
        } else if(!h[x]) {
            h[f[x]]=0;
            f[x]=0;
        } else {
            h[f[x]]=h[x];
            f[h[x]]=f[x];
            f[x]=h[x]=0;
        }
        if(!h[y]) {
            f[x]=y;
            h[y]=x;
        } else {
            f[x]=y;
            h[x]=h[y];
            h[y]=f[h[x]]=x;
        }
        /*int tail=head;
        while(tail) {
            printf("%d ",tail);
            tail=h[tail];
        }
        printf("\n");*/
    }
    while(head) {
        printf("%d ",head);
        head=h[head];
    }
    return 0;
}

注意考虑特殊情况(好像这道题不考虑也没事)
题面传送门
这道题用开放寻址法被卡了,只能用挂链表法。
代码实现:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int n,ans,h[1000007],head,z[1000007],tot;
string a,f[1000007];
inline void get(string a){
    register int i,tmp,longge=a.size();ans=0;
    for(i=0;i<longge;i++) ans=(ans*259+a[i])%1000039;
    head++;
    f[head]=a;
    z[head]=h[ans];
    h[ans]=head;
     
}
inline int find(string a){
    register int i,tmp,now=0,longge=a.size();ans=0;
    for(i=0;i<longge;i++) ans=(ans*259+a[i])%1000039;
    tmp=h[ans];
    while(tmp>=0){
        if(f[tmp]==a) now++;
        tmp=z[tmp];
    }
    return now;
}
int main(){
    register int i;
    memset(h,-1,sizeof(h));
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        cin>>a;
        if(!find(a)) tot++,get(a);
    }
    printf("%d",tot);
}

题面传送门
这道题要用邻接表来存图。
我们给每一个点做一个链表,只不过这些链表放在一个数组里。每个链表有一个头,我们每次加入都要从头加入。这样遍历时顺着头一路找回去就可以了。
代码实现:

#include<cstdio>
#include<cstring>
using namespace std;
int n,m,x[39],y[39],head,v[39],h[39];
struct yyy{
    int to,z;
}f[39];
inline void add(int x,int y){
    head++;
    f[head].to=y;
    f[head].z=h[x];
    h[x]=head;
}
inline void dfs(int x){
    if(v[x]) return;
    v[x]=1;
    printf("%d ",x);
    for(register int i=h[x];i!=-1;i=f[i].z) dfs(f[i].to);
    return ;
}
int main(){
    memset(h,-1,sizeof(h));
    register int i;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]);
    for(i=m;i>=1;i--) add(x[i],y[i]),add(y[i],x[i]);
    dfs(1);
    return  0;
}

链表可以应用在很多地方,但是链表只是指针的一个应用,所以我们还是学好指针吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值