SDUT数据结构与算法pta--排序

用了一些自认为比较简单的方法解决的,比较适合快速完成实验

7-1 统计工龄

给定公司 n 名员工的工龄,要求按工龄增序输出每个工龄段有多少员工。

输入格式:

输入首先给出正整数 n(≤105),即员工总人数;随后给出 n 个整数,即每个员工的工龄,范围在 [0, 50]。

输出格式:

按工龄的递增顺序输出每个工龄的员工个数,格式为:"工龄:人数"。每项占一行。如果人数为 0 则不输出该项。

输入样例:

复制代码
8
10 2 0 5 7 2 5 2

输出样例:

复制代码
0:1
2:3
5:2
7:1
10:1

结果:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
map<int, int> mp;

int main()
{

  int n;
  cin >> n;
  for (int i = 0; i < n; i++)
  {
    int x;
    cin >> x;
    mp[x]++;
  }
  // map 默认按key升序排列
  for (auto it = mp.begin(); it != mp.end(); it++)
  {
    cout << it->first << ":" << it->second << endl;
  }
}

7-2 寻找大富翁

胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人。假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁。

输入格式:

输入首先给出两个正整数N(≤106)和M(≤10),其中N为总人数,M为需要找出的大富翁数;接下来一行给出N个人的个人资产值,以百万元为单位,为不超过长整型范围的整数。数字间以空格分隔。

输出格式:

在一行内按非递增顺序输出资产排前M位的大富翁的个人资产值。数字间以空格分隔,但结尾不得有多余空格。

输入样例:

复制代码
8 3
8 12 7 3 20 9 5 18

输出样例:

复制代码
20 18 12
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6;
int a[N];
int main()
{

  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++)
  {
    cin >> a[i];
  }
  sort(a, a + n);
  int flag = 0;

  if (m > n)//!!!!!!!!!!!!
    m = n;

  for (int i = 1; i <= m; i++)
  {
    if (flag == 0)
    {
      cout << a[n - i];
      flag = 1;
    }

    else
      cout << " " << a[n - i];
  }
}

7-3 点赞狂魔

微博上有个"点赞"功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为"点赞狂魔"。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。

输入格式:

输入在第一行给出一个正整数N(≤100),是待统计的用户数。随后N行,每行列出一位用户的点赞标签。格式为"Name K F1​⋯FK​",其中Name是不超过8个英文小写字母的非空用户名,1≤K≤1000,Fi​(i=1,⋯,K)是特性标签的编号,我们将所有特性标签从 1 到 107 编号。数字间以空格分隔。

输出格式:

统计每个人点赞的不同标签的数量,找出数量最大的前3名,在一行中顺序输出他们的用户名,其间以1个空格分隔,且行末不得有多余空格。如果有并列,则输出标签出现次数平均值最小的那个,题目保证这样的用户没有并列。若不足3人,则用-补齐缺失,例如mike jenny -就表示只有2人。

输入样例:

复制代码
5
bob 11 101 102 103 104 105 106 107 108 108 107 107
peter 8 1 2 3 4 3 2 5 1
chris 12 1 2 3 4 5 6 7 8 9 1 2 3
john 10 8 7 6 5 4 3 2 1 7 5
jack 9 6 7 8 9 10 11 12 13 14

输出样例:

复制代码
jack chris john
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int n;
set<int> st;
struct node
{
  int num, cnt;
  string name;
} f[N];
bool cmp(node a, node b)
{
  if (a.cnt == b.cnt)
    return a.num < b.num;
  return a.cnt > b.cnt;
}
int main()
{
  cin >> n;
  for (int i = 0; i < n; i++)
  {
    cin >> f[i].name >> f[i].num;
    for (int j = 0; j < f[i].num; j++)
    {
      int x;
      cin >> x;
      st.insert(x);
    }
    f[i].cnt = st.size();
    st.clear();
  }
  sort(f, f + n, cmp);
  int flag = 0;
  for (int i = 0; i < 3; i++)
  {
    if (flag)
      cout << " ";
    flag = 1;
    if (i < n)
      cout << f[i].name;
    else
      cout << "-";
  }
}

7-4 插入排序还是归并排序

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 n (≤100);随后一行给出原始序列的 n 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 行中输出Insertion Sort表示插入排序、或Merge Sort表示归并排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

输入样例 1:

复制代码
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出样例 1:

复制代码
Insertion Sort
1 2 3 5 7 8 9 4 6 0

输入样例 2:

复制代码
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

输出样例 2:

复制代码
Merge Sort
1 2 3 8 4 5 7 9 0 6
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int a[N], s[N];
int n;
int main()
{
  cin >> n;
  for (int i = 0; i < n; i++)
  {
    cin >> a[i];
  }
  for (int i = 0; i < n; i++)
    cin >> s[i];
  int i = 0, j;
  while (i < n && s[i] <= s[i + 1])
  {
    i++;
  }
  j = i + 1;
  while (j < n && a[j] == s[j])
  {
    j++;
  }
  if (j == n)
  {
    cout << "Insertion Sort" << endl;
    sort(a, a + min(i + 2, n));
  }
  else
  {
    cout << "Merge Sort" << endl;
    int flag = 1, step = 1;
    while (flag)
    {
      flag = 0;
      for (int i = 0; i < n; i++)
      {
        if (a[i] != s[i])
          flag = 1;
      }
      step *= 2;
      for (int i = 0; i < n; i += step)
      {
        sort(a + i, a + min(i + step, n));
      }
    }
  }
  int flag = 0;
  for (int i = 0; i < n; i++)
  {
    if (flag)
      cout << " ";
    flag = 1;
    cout << a[i];
  }
}

7-5 插入排序还是堆排序

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

堆排序也是将输入分为有序和无序两部分,迭代地从无序部分找出最大元素放入有序部分。它利用了大根堆的堆顶元素最大这一特征,使得在当前无序区中选取最大元素变得简单。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数 n (≤100);随后一行给出原始序列的 n 个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第 1 行中输出 Insertion Sort 表示插入排序、或 Heap Sort 表示堆排序;然后在第 2 行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行首尾不得有多余空格。

输入样例 1:

复制代码
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

输出样例 1:

复制代码
Insertion Sort
1 2 3 5 7 8 9 4 6 0

输入样例 2:

复制代码
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9

输出样例 2:

复制代码
Heap Sort
5 4 3 1 0 2 6 7 8 9
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int a[N], s[N];
int n,r;
void down(int u)
{
  int t=u;
  if(u*2<=r&&s[u*2]>s[t])  t=u*2;
  if(u*2+1<=r&&s[u*2+1]>s[t]) t=u*2+1;
  if(u!=t)
  {
    swap(s[t],s[u]);
    down(t);
  }
}
int main()
{
  cin >> n;
  for (int i = 1; i <=n; i++)
  {
    cin >> a[i];
  }
  for (int i =1; i <= n; i++)
    cin >> s[i];

 if(s[1]>s[2])
 {
cout<<"Heap Sort"<<endl;
int tt;
for(int i=1;i<=n;i++)
{
  if(s[1]<s[i])
  {
    tt=i;
    break;
  }
}
swap(s[1],s[tt-1]);
r=tt-2;
down(1);
 }

  else
  {
     cout << "Insertion Sort" << endl;
    int i=1;
    while(i<=n&&s[i]<=s[i+1]) i++;
    sort(s, s + min(i + 2, n));
  }
  int flag = 0;
  for (int i = 1; i <=n; i++)
  {
    if (flag)
      cout << " ";
    flag = 1;
    cout << s[i];
  }

}

7-6 逆序对

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。

最近,TOM 老猫查阅到一个人类称之为"逆序对"的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai​>aj​ 且 i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。

输入格式:

第一行,一个数 n,表示序列中有 n个数。

第二行 n 个数,表示给定的序列。序列中每个数字不超过 109。

输出格式:

输出序列中逆序对的数目。

输入样例:

在这里给出一组输入。例如:

复制代码
6
5 4 2 6 3 1

输出样例:

在这里给出相应的输出。例如:

复制代码
11

提示

对于 25% 的数据,n≤2500

对于 50% 的数据,n≤4×104。

对于所有数据,n≤5×105

请使用较快的输入输出

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, a[N], b[N];
long long res;//!!!!!!!!!!!!!!1111111
void msort(int l, int r)
{
  if (l == r)
    return;
  int mid = l + r >> 1;
  msort(l, mid);
  msort(mid + 1, r);
  int i = l;       // a
  int j = mid + 1; // a
  int k = l;       // b
  while (i <= mid && j <= r)
  {
    if (a[i] <= a[j])
      b[k++] = a[i++];
    else
      b[k++] = a[j++], res += mid - i + 1;
  }
  while (i <= mid)
    b[k++] = a[i++];
  while (j <= r)
    b[k++] = a[j++];
  for (int i = l; i <= r; i++)
    a[i] = b[i];
}
int main()
{
  cin >> n;
  for (int i = 0; i < n; i++)
    cin >> a[i];
  msort(0, n - 1);
  cout << res << endl;
}

7-7 堆排序

给定一个整数序列,请按非递减序输出采用堆排序的各趟排序后的结果。

输入格式:

测试数据有多组,处理到文件尾。每组测试数据第一行输入一个整数n(1≤n≤100),第二行输入n个整数。

输出格式:

对于每组测试,输出若干行,每行是一趟排序后的结果,每行的每两个数据之间留一个空格。

输入样例:

复制代码
4
8 7 2 1
8
40 55 49 73 12 27 98 81

输出样例:

复制代码
7 1 2 8
2 1 7 8
1 2 7 8
81 73 49 55 12 27 40 98
73 55 49 40 12 27 81 98
55 40 49 27 12 73 81 98
49 40 12 27 55 73 81 98
40 27 12 49 55 73 81 98
27 12 40 49 55 73 81 98
12 27 40 49 55 73 81 98
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000;
int heap[N];
int n, r;
void up(int u)
{
  while (u / 2 && heap[u / 2] > heap[u])
  {
    swap(heap[u / 2], heap[u]);
    u /= 2;
  }
}
void down(int u)
{
  int t = u;
  if (u * 2 <= r && heap[u * 2] > heap[t])
    t = u * 2;
  if (u * 2 + 1 <= r && heap[u * 2 + 1] > heap[t])
    t = u * 2 + 1;
  if (u != t)
  {
    swap(heap[u], heap[t]);
    down(t);
  }
}
int main()
{
  ios::sync_with_stdio(false);
  while (cin >> n)
  {
    for (int i = 1; i <= n; i++)
    {
      cin >> heap[i];
    }
    r = n;
    for (int i = n / 2; i >= 1; i--)
    {
      down(i);
    }
    for (int i = 1; i <= n - 1; i++)
    {
      swap(heap[1], heap[r]);
      r--;
      down(1);
      int flag = 0;
      for (int j = 1; j <= n; j++)
      {
        if (flag)
          cout << " ";
        flag = 1;
        cout << heap[j];
      }
      cout << endl;
    }
  }
}

7-8 寻找第k小的数

给定若干整数,请设计一个高效的算法,确定第k小的数。

输入格式:

测试数据有多组,处理到文件尾。每组测试数据的第1行输入2个整数n,k(1≤k≤n≤1000000)。第2行输入n个整数,每个数据的取值范围在0到1000000之间。

输出格式:

对于每组测试,输出第k小的数。

输入样例:

复制代码
5 3
1 2 2 2 1
9 3
1 2 3 4 5 6 9 8 7

输出样例:

复制代码
2
3
cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int a[N];
int m, n;
int main()
{
  ios::sync_with_stdio(false);//加上 正好卡过
  while (cin >> n >> m)
  {
    for (int i = 1; i <= n; i++)
    {
      cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    cout << a[m] << endl;
  }
}

7-9 链式基数排序

实现链式基数排序,待排序关键字n满足1≤n≤1000,最大关键字数位≤5。

输入样例:

第一行输入待排序个数n(1≤n≤1000),再输入n个数(n的数位≤5)。

复制代码
10
278 109 63 930 589 184 505 269 8 83

输出样例:

输出每趟分配-收集后链表中的关键字,趟数为序列中最大值的数位(如样例中930的数位为3),每行结尾有空格。

复制代码
930 63 83 184 505 278 8 109 589 269 
505 8 109 930 63 269 278 83 184 589 
8 63 83 109 184 269 278 505 589 930 
cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,x;
vector<int>a;
int main()
{
int maxx=0;
cin>>n;
for(int i=1;i<=n;i++)
{
  cin>>x;
  string s=to_string(x);
  int t=s.size();
  maxx=max(maxx,t);
  a.push_back(x);
}
int cnt=1;
while(maxx--)
{
  vector<int>v[10];
  for(int i=0;i<n;i++)
  {
    int tt=(a[i]/cnt)%10;
    v[tt].push_back(a[i]);
  }
  cnt*=10;
  a.clear();
  for(int i=0;i<10;i++)
  {
    for(int j=0;j<v[i].size();j++)
    {
      a.push_back(v[i][j]);
    }
  }
  for(int i=0;i<n;i++)
  {
    cout<<a[i]<<" ";
  }
  cout<<endl;
}
}
相关推荐
大江东去浪淘尽千古风流人物1 小时前
【MSCKF】零空间 UpdaterHelper::nullspace_project_inplace 的实现细节,MSCKF边缘化含义
算法·性能优化·vr·dsp开发·mr
AndrewHZ1 小时前
【图像处理基石】图像处理中的色彩经典算法原理与实战解析
图像处理·算法·计算机视觉·白平衡·色彩科学·经典算法·k means
Dev7z1 小时前
基于Matlab多算法的图像增强与客观质量评价系统
人工智能·算法·matlab
xcLeigh1 小时前
【新】Rust入门:基础语法应用
开发语言·算法·rust
小年糕是糕手1 小时前
【C++同步练习】类和对象(一)
java·开发语言·javascript·数据结构·c++·算法·排序算法
小O的算法实验室1 小时前
2025年IJPR SCI2区,基于混合邻域结构的高效稳定智能调度算法用于柔性作业车间调度,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
小年糕是糕手1 小时前
【C++同步练习】类和对象(二)
java·开发语言·javascript·数据结构·c++·算法·ecmascript
沙白猿1 小时前
B树 / B+树
数据结构·b树·算法
我不是彭于晏丶1 小时前
74. 搜索二维矩阵
数据结构·算法