题目链接:ALDS1_2_C:Stable Sort
题目概要:
扑克牌中存在数字相同而花色不同的情况,该题需要利用扑克牌这一特性来比较两种排序:冒泡排序、选择排序(题中给出伪代码)的稳定性。在《挑战程序设计竞赛》中,书中给出的参考答案默认了冒泡排序是稳定的,显然该代码在比较任意两种排序算法时,无法得出客观结果,这里我给出一种能比骄傲任意排序算法稳定性的算法,在AOJ上能够AC。
代码思路:
该题所要解决的关键问题是,如何相同数字(Value)不同花色(Suit)的牌,在排序前后的相对位置是否改变,若改变则不稳定,不改变则稳定。显然用暴力循环来判断容易超出题目限制,我的方法是,构造一个新的数组first[],first[i]表示数字为i的牌第一次出现的花色,由初始牌组构造一个firstA[],排序后的牌组再次构造firstB[],最后比较两数组是否相同即可。
代码如下:
#include<stdio.h>
#include<iostream>
using namespace std;
char firstA[36], firstB[36], firstS[36];//初始化first数组:原始牌组、B种排序、S种排序
struct Card
{
int value;
char suit;
}A[100], S[100], B[100];//牌组数组
void check(char first[], Card C[], int n)//利用牌组数组生成first数组函数
{
for (int i = 0; i < n; i++)
{
int value = C[i].value;
if (first[value] == 0) first[value] = C[i].suit;
}
}
void BubbleSort(int n, Card A[])//冒泡排序算法
{
for (int i = 0; i < n; i++)
{
for(int j = n-1; j > i; j--)
if (A[j].value < A[j - 1].value)
{
Card t = A[j];
A[j] = A[j - 1];
A[j - 1] = t;
}
}
}
void SelectionSort(int n, Card A[])//选择排序算法
{
for (int i = 0; i < n; i++)
{
int minj = i;
for (int j = i; j < n; j++)
{
if (A[j].value < A[minj].value) minj = j;
}
Card t = A[i];
A[i] = A[minj];
A[minj] = t;
}
}
void Print(Card A[], int n)//输出牌组算法
{
for (int i = 0; i < n; i++)
{
if (i) cout << ' ';
cout << A[i].suit << A[i].value;
}
printf("\n");
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)//读入牌组
{
char s[5] = {};
cin >> s;
A[i].suit = s[0];
A[i].value = s[1]-48;
}
copy(A, A+100, B);
copy(A, A+100, S);
BubbleSort(n, B);
SelectionSort(n, S);
check(firstA, A, n);//生成first数组
check(firstB, B, n);
check(firstS, S, n);
int flagB = 1, flagS = 1;//是否稳定标识符
for (int i = 0; i < n; i++)
{
if(flagB)
if (firstB[i] != firstA[i]) flagB = 0;
if (flagS)
if (firstS[i] != firstA[i]) flagS = 0;
}
Print(B, n);
if (flagB) cout << "Stable" << endl;
else cout << "Not stable" << endl;
Print(S, n);
if (flagS) cout << "Stable" << endl;
else cout << "Not stable" << endl;
return 0;
}
代码很烂,还有很多可以改进的地方,欢迎讨论!