算法与数据结构第六次作业——排序
算法与数据结构实验题 5.12 Bubble Sort
★实验任务 给定一个 1~N 的排列P ,即1到N中的每个数在P中都出现一次。
现在要对排列P进行冒泡排序,代码如下:
for (int i = 1; i <= N; ++i)
for (int j = N, t; j > i; ‐‐j)
if (P[j ‐ 1] > P[j])
t = P[j], P[j] = P[j ‐ 1], P[j ‐ 1] = t;
在排序过程中,数字的位置可能会发生变化。对于1~N的每个数字,你需要输出过程中达到的最左位置下标和最右位置下标的差的绝对值。
80%的数据:N<=1000
100%的数据:N<=100000
输入示例
4
3 2 1 4
输出示例
2 1 2 0
Hint
样例冒泡排序过程:
swap 2 1: 3 2 1 4 > 3 1 2 4
swap 3 1: 3 1 2 4 > 1 3 2 4
swap 3 2: 1 3 2 4 > 1 2 3 4
这道题目的破题点在于如何将每个数字到达的最左侧和最右侧的位置找到。需要自己多模拟几次过程,就可以发现:每个数字到达的最右侧位置,其实就是看这个数字的右侧有几个比他小的数字,而最左侧位置就取初始位置和排序完成后的位置中较小的那一个。
考虑到数据的大小,需要采用归并的思想来解答。
- 初版代码(采用冒泡模拟的方法,数据较大的点超时)
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int* a = new int[n];
int* b = new int[n];
int* min = new int[n];
int* max = new int[n];
for (int i = 0; i < n; i++)
{
cin >> a[i];
b[i] = a[i];
min[a[i] - 1] = i;
max[a[i] - 1] = i;
}
for (int i = n-1; i >= 0; i--)
{
for (int j = 0,t; j < i; j++)
{
if (a[j] > a[j+1])
{
t = a[j], a[j] = a[j + 1], a[j + 1] = t;
if (max[a[j] - 1] < j) max[a[j] - 1] = j;
if (min[a[j] - 1] > j) min[a[j] - 1] = j;
if (max[a[j + 1] - 1] < j+1) max[a[j + 1] - 1] = j+1;
if (min[a[j + 1] - 1] > j+1) min[a[j + 1] - 1] = j+1;
}
}
}
for (int i = 0; i < n; i++)
{
int pos = max[i] - min[i];
cout << pos << ' ';
}
}
- 归并做法(与归并排序类似)
#include<iostream>
#include<cstdio>
using namespace std;
int Right[100001] = { 0 };
int Left[100001] = { 0 };
int Pos[100001] = { 0 };
void merge(int a[], int left, int mid, int right)
{
int l_pos = left;
int r_pos = mid+1;
int pos = left;
int sum = 0;
for (int i = left; i <= mid; i++)
{
Left[i] = a[i];
}
for (int i = mid+1; i <= right; i++)
{
Right[i] = a[i];
}
while (l_pos <= mid && r_pos <= right)
{
if (Left[l_pos] > Right[r_pos])
{
sum++;
a[pos++] = Right[r_pos++];
}
else
{
Pos[Left[l_pos]] += sum;
a[pos++] = Left[l_pos++];
}
}
while (l_pos <= mid)
{
Pos[Left[l_pos]] += sum;
a[pos++] = Left[l_pos++];
}
while (r_pos <= right)
{
a[pos++] = Right[r_pos++];
}
}
void msort(int a[], int left, int right)
{
if (left < right)
{
int mid = (left + right) / 2;
msort(a, left, mid);
msort(a, mid + 1, right);
merge(a, left, mid, right);
}
}
int min(int a, int b)
{
if (a > b) return b;
else return a;
}
int main()
{
int a[100001]; int b[100001];
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf_s("%d", &a[i]);
b[a[i]] = i;
}
msort(a, 1, n);
for (int i = 1; i <= n; i++)
{
cout << b[i] + Pos[i] - min(i, b[i])<<' ';
}
}