ALDS1_2_C:Stable Sort

题目链接: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;
}

代码很烂,还有很多可以改进的地方,欢迎讨论!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值