蓝桥之链表

最近真的特别焦虑,体测、比赛和考试一个接一个,让人喘不过气来QAQ

甚至考试和比赛还有冲突,sad

最近因为看了牙,打了药的缘故,一直在吃素QAQ

本来今天还想写个知识点总结的,但是太晚了,现在已经快凌晨1点了,而且黑灯瞎火的坐在床上小心翼翼(怕打扰到舍友睡觉)的敲代码真的很痛苦,以后有时间就补上!

明天早上七点半还得到小操场集合,学校在搞社团文化活动QAQ


1.自行车停放

题目描述

有 n 辆自行车依次来到停车棚,除了第一辆自行车外,每辆自行车都会恰好停放在已经在停车棚里的某辆自行车的左边或右边。(e.g.停车棚里已经有 3辆自行车,从左到右编号为:3,5,1。现在编号为2的第4辆自行车要停在5 号自行车的左边,所以现在停车棚里的自行车编号是:3,2,5,1)。给定n辆自行车的停放情况,按顺序输出最后停车棚里的自行车编号。n < 100000。

输入描述

第一行一个整数 n 。第二行一个整数 x 。表示第一辆自行车的编号。 以下n -1行,每行3个整数x,y,z。z = 0 时,表示编号为 x 的自行车恰停放在编号为 y 的自行车的左边。z = 1时,表示编号为 x 的自行车恰停放在编号为 y 的自行车的右边。

输出描述

从左到右输出停车棚里的自行车编号

输入输出样例

示例

输入

4

3
1 3 1
2 1 0
5 2 1

输出

3 2 5 1 


按照书中的教程,应该是用个链表来做,但是为了省事,我用的vector数组

先把第一个给定的元素放到vector数组中,然后循环来判断每组给定的数据,用find找到编号为y的自行车,如果z = 0,就把x 插入insert()到y的左边,否则,插入到y的右边。最后按格式输出。


C++ 

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 100010;
vector<int> a(N);
int main()
{
  int n,x;
  cin>>n>>x;
  a[0] = x;
  for(int i = 1;i<n;i++){
      int y,z;
      cin>>x>>y>>z;
      auto it = find(a.begin(),a.end(),y);
      if(z == 0) a.insert(it,x);
      else a.insert(it + 1,x);   
  }
  cout<<a[0];
  for(int i = 1;i<n;i++)
    cout<<" "<<a[i];
  return 0;
}

2.小王子单链表

题目描述

小王子有一天迷上了排队的游戏,桌子上有标号为 1- 10 的 10 个玩具,现在小王子将他们排成一列,可小王子还是太小了,他不确定他到底想把那个玩具摆在哪里,直到最后才能排成一条直线,求玩具的编号。已知他排了M次,每次都是选取标号为 X 个放到最前面,求每次排完后玩具的编号序列。


要求一:采用单链表解决

输入描述

第一行是一个整数 M,表示小王子排玩具的次数。
随后 M 行每行包含一个整数 X,表示小王子要把编号为 X 的玩具放在最前面。

输出描述

共 M 行,第i行输出小王子第i次排完序后玩具的编号序列。

输入输出样例

示例 1

输入
 

5

3

2

3

4

2

输出

3 1 2 4 5 6 7 8 9 10

2 3 1 4 5 6 7 8 9 10

3 2 1 4 5 6 7 8 9 10

4 3 2 1 5 6 7 8 9 10

2 4 3 1 5 6 7 8 9 10 


按要求来哦~题目中说要采用单链表来完成

可以定义一个结构体,存放当前节点的data和指向下一个数据的指针。用数组来模拟~

对于单链表来说,如何找到它的前驱是个问题,所以你最好定义一个函数来查找前驱,通过for循环遍历链表中的每一个节点,并存储它的前驱,如果找到了x的前驱,就退出循环,返回x的前驱

最后在主函数中把x的指针指向改动一下,这个最好在纸上画画,思路会比较清晰,也不容易出错


C++ 

#include <iostream>
using namespace std;
const int N = 20;
struct Node{
    int data;
    int next;
}node[N];
int del(int x){
    int pre = 0;
    for(int it = node[0].next;it!=-1;){
        if(node[it].data == x) return pre;
        pre = it;
        it = node[it].next;
    }
    return pre;
}
int main(){
    int m;
    cin>>m;
    node[0].next = 1;
    for(int i = 1;i<=10;i++)//数据存放到单链表中
    {
        node[i].data = i;
        node[i].next = i + 1;
    }
    node[10].next = -1;
    while(m--){
        int x;
        cin>>x;
        int pre = del(x);
        node[pre].next = node[x].next;
        node[x].next = node[0].next;
        node[0].next = x;
        cout<<x;
        x = node[x].next;
        for(int i = 1;i<10;i++)
        {
            cout<<" "<<x;
            x = node[x].next;
        }
        cout<<endl;
    }
    return 0;
}

 3.小王子双链表

题目描述

小王子有一天迷上了排队的游戏,桌子上有标号为1-10 的 10 个玩具,现在小王子将他们排成一列,可小王子还是太小了,他不确定他到底想把那个玩具摆在哪里,直到最后才能排成一条直线,求玩具的编号。已知他排了M次,每次都是选取标号为 X 个放到最前面,求每次排完后玩具的编号序列。

要求一:采用循环链表解决

输入描述

第一行是一个整数 M,表示小王子排玩具的次数。随后 M 行每行包含一个整数 X,表示小王子要把编号为 X 的玩具放在最前面。

输出描述

共 M 行,第i行输出小王子第i次排完序后玩具的编号序列。

输入输出样例

示例1

输入

5

3

2

3

4

2

输出

3 1 2 4 5 6 7 8 9 10

2 3 1 4 5 6 7 8 9 10

3 2 1 4 5 6 7 8 9 10

4 3 2 1 5 6 7 8 9 10

2 4 3 1 5 6 7 8 9 10 


按要求来哦~题目中说要采用双链表来完成,双链表的话,对于找前驱就不是很费劲啦~

比较容易出错的点就是指针的移动,如果你要删除x,x的前一个节点的next指针和后一个节点的pre指针都要改动,在着,你把x移动到最前面,鉴于本链表是个循环链表,所以你插入的位置的前一个位置的next要变,插入位置的后一个位置的pre指针也要变才可以 ^^


C++ 

#include <iostream>
using namespace std;
const int N = 20;
struct Node{
    int pre;
    int next;
}a[N];
int main()
{
  int m;
  cin>>m;
  a[0].next = 1;
  for(int i = 1;i<=10;i++){
      a[i].next = i + 1;
      a[i].pre = i - 1;
  }
  a[10].next = 1;
  a[1].pre = 10;
  while(m--){
      int x;
      cin>>x;
      int prev = a[x].pre;//x的前驱
      int nex = a[x].next;//x的后继
      //删除
      a[prev].next = a[x].next;
      a[nex].pre = a[x].pre;
      //插入
      int first = a[0].next;
      int end = a[0].pre;
      a[x].next = first;
      a[x].pre = end;
      a[first].pre = x;
      a[end].next = x;
      a[0].next = x;
      cout<<x;
      for(int i = 1;i<10;i++)
      {
          cout<<" "<<a[x].next;
          x = a[x].next;
      }
      cout<<endl;
  }
  return 0;
}

4.约瑟夫环


题目描述


设有 n 个人围坐在圆桌周围,现从某个位置k上的人开始报数,报数到 m的人就站出来。下一个人,即原来的第 m +1个位置上的人,又从1开始报数,再报数到 m 的人站出来。依次重复下去,直到全部的人都站出来为止。试设计一个程序求出这 n 个人的出列顺序。 

要求一:采用循环链表解决。
要求二:可以使用模拟法,模拟循环链表。
要求三:可以不使用循环链表类的定义使用方式。


输入描述

输入只有一行且为用空格隔开的三个正整数 n,k,m,其含义如上所述。

输出描述

共 n 行,表示这 几 个人的出列顺序。

输入输出样例

示例 1

输入
 

3 5 8

输出

3

2


如果不是这道题,我写博客就不会这么晚

不过这道题也暴露了我指针学的不怎么踏实

这道题多亏有魏佬指点,才能够通过,在这里表示感谢,^^

最后又改进了一下

哈哈,一波三折的一道题

上面的题巩固了一下单链表,循环链表,所以这个题我用的STL的list做的,至于题目中说的三个要求,以后有时间再补上吧^^

先把这十个数字存到表里面,然后迭代器找到k所对应的位置,每次循环m次,找到要删除的位置,输出位置对应的值,最后用erase删除,循环结束的条件是表中再无数据


C++ 

#include<iostream>
#include<list>
using namespace std;
list<int> node;
int main(){
  int n,k,m;
  cin>>n>>k>>m;
  for(int i = 1;i<=n;i++)
    node.push_back(i);
  auto it = node.begin();
  for(int i = 1;i<k;i++)
    {
      ++it;
      if(it == node.end()) it = node.begin();
    }
  while(node.size()){
    for(int j = 1;j<m;j++){
      ++it;
      if(it == node.end()) it = node.begin();
    }
    cout<<*it<<endl;
    it = node.erase(it);
    if(it == node.end()) it = node.begin();
  }
  return 0;
}

我以为我电脑能撑到我写完,结果关机了hh

这里附一下一波三折的过程~做下记录


一开始我写的代码(怎么都对不了):

#include<iostream>
#include<list>
using namespace std;
list<int> node;
int main(){
  int n,k,m;
  cin>>n>>k>>m;
  for(int i = 1;i<=n;i++)
    node.push_back(i);
  auto it = node.begin();
  for(int i = 1;i<k;i++)
    {
      ++it;
      if(it == node.end()) it = node.begin();
    }
  while(node.size()){
    for(int j = 1;j<m;j++){
      ++it;
      if(it == node.end()) it = node.begin();
    }
    auto tt = it;
    cout<<*it<<endl;
    node.erase(it);
    it = ++tt;
    if(it == node.end()) it = node.begin();
  }
  return 0;
}

后来求助魏佬 ,大佬果然是大佬,一眼看出问题所在,这里附上截图~

后来我发现其实根本用不到tt,所以又改进了一下 ~才有了这最后的结果


ending~

今明两天准备计算机网络的期中考试QAQ 

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值