稳定排序

本文介绍了一个算法案例,通过对比原始数据和排序后的数据来判断排序算法的正确性和稳定性。涉及了如何定义排序稳定性及其实现方法,适用于学习排序算法原理和技术的同学。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家都知道,快速排序是不稳定的排序方法。 
如果对于数组中出现的任意a[i],a[j](i<j),其中a[i]==a[j],在进行排序以后a[i]一定出现在a[j]之前,则认为该排序是稳定的。 

某高校招生办得到一份成绩列表,上面记录了考生名字和考生成绩。并且对其使用了某排序算法按成绩进行递减排序。现在请你判断一下该排序算法是否正确,如果正确的话,则判断该排序算法是否为稳定的。 
Input本题目包含多组输入,请处理到文件结束。 
对于每组数据,第一行有一个正整数N(0<N<300),代表成绩列表中的考生数目。 
接下来有N行,每一行有一个字符串代表考生名字(长度不超过50,仅包含'a'~'z'),和一个整数代表考生分数(小于500)。其中名字和成绩用一个空格隔开。 
再接下来又有N行,是上述列表经过某排序算法以后生成的一个序列。格式同上。Output对于每组数据,如果算法是正确并且稳定的,就在一行里面输出"Right"。如果算法是正确的但不是稳定的,就在一行里面输出"Not Stable",并且在下面输出正确稳定排序的列表,格式同输入。如果该算法是错误的,就在一行里面输出"Error",并且在下面输出正确稳定排序的列表,格式同输入。 

注意,本题目不考虑该排序算法是错误的,但结果是正确的这样的意外情况。Sample Input
3
aa 10
bb 10
cc 20
cc 20
bb 10
aa 10
3
aa 10
bb 10
cc 20
cc 20
aa 10
bb 10
3
aa 10
bb 10
cc 20
aa 10
bb 10
cc 20
Sample Output
Not Stable
cc 20
aa 10
bb 10
Right
Error
cc 20
aa 10
bb 10
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct people{
	char name[100];
	int grade,id;
}date[400],date2[400];
bool cmp(people a,people b){
	if(a.grade==b.grade) return a.id<b.id;
	return a.grade>b.grade;
}            //注意用id表示每项的数位,这点卡了好多次
int main(){
	int N;
	while(scanf("%d",&N)!=EOF){
		int x=0,y=0; 
		for(int i=0;i<N;i++){
			scanf("%s %d",&date[i].name,&date[i].grade);
			date[i].id=i;
		}
		sort(date,date+N,cmp);
		for(int i=0;i<N;i++){
			scanf("%s %d",&date2[i].name,&date2[i].grade);
			date2[i].id=i;
		}
		for(int i=0;i<N;i++){
			int n=strcmp(date[i].name,date2[i].name);
			int m=date[i].grade-date2[i].grade;
			if(n!=0||m!=0) break;
			if(i==N-1) printf("Right\n");
			y++;
		}
		for(int i=0;i<N;i++){
			int n=date[i].grade-date2[i].grade;
			if(n!=0) break;
			if(i==N-1&&y!=N) printf("Not Stable\n");
			x++;
		}
		if(x!=N) printf("Error\n");
		if(y!=N){
			for(int i=0;i<N;i++){
				printf("%s %d\n",date[i].name,date[i].grade);
			}
		}
	}
	return 0;
}

### 稳定排序算法概述 稳定排序是指在排序过程中能够保持具有关键字的记录之间的对位置不变的一类排序方法。以下是几种常见的稳定排序算法及其特点: #### 1. **冒泡排序 (Bubble Sort)** 冒泡排序是一种简单的交换排序,在每一轮迭代中,邻元素两两比较并按需交换,最终使得较大的元素逐步“浮”到数组末端。由于每次只移动一位,因此不会改变等元素间的初始顺序[^4]。 #### 2. **插入排序 (Insertion Sort)** 插入排序通过构建有序序列的方式工作,它从第二个元素开始向前逐一扫描已排序部分,并将其正确放置其中。此特性决定了即使遇到重复也不会打乱它们原有的排列关系[^3]。 #### 3. **归并排序 (Merge Sort)** 归并排序基于分治策略,递归地把待排序区间分成更小子集直到每个子集中只有一个元素为止;接着再把这些小集合合并起来形成新的更大规模的有序列表。在整个分裂与重组的过程中都严格遵循稳定性原则[^2]。 #### 4. **计数排序 (Counting Sort)** 计数排序适用于一定范围内的整数排序问题。该算法统计输入数据各个数出现次数之后重新安排这些数字的位置从而得到完全有序的结果。因其非比较性质故天然具备稳定性[^4]。 #### 5. **基数排序 (Radix Sort)** 基数排序按照低位优先级逐位进行分配收集操作直至最高位处理完毕即完成整体排序过程。只要所使用的辅助排序技术本身是稳定的(比如这里用的是计数排序),那么整个基数排序就是稳定的[^4]。 --- ### 示例代码展示 以下提供了一些典型稳定排序算法的具体实现: ```python def bubble_sort(arr): n = len(arr) for i in range(n): swapped = False for j in range(0, n-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] swapped = True if not swapped: break return arr def insertion_sort(arr): for i in range(1, len(arr)): key = arr[i] j = i - 1 while j >= 0 and key < arr[j]: arr[j + 1] = arr[j] j -= 1 arr[j + 1] = key return arr def merge_sort(arr): if len(arr) <= 1: return arr mid = len(arr)//2 left_half = merge_sort(arr[:mid]) right_half = merge_sort(arr[mid:]) merged_arr = [] l_idx = r_idx = 0 while l_idx < len(left_half) and r_idx < len(right_half): if left_half[l_idx] <= right_half[r_idx]: merged_arr.append(left_half[l_idx]) l_idx += 1 else: merged_arr.append(right_half[r_idx]) r_idx += 1 merged_arr.extend(left_half[l_idx:]) merged_arr.extend(right_half[r_idx:]) return merged_arr ``` --- ### 总结说明 以上列举了几种典型的稳定排序算法,包括但不限于冒泡排序、插入排序、归并排序以及线性时间复杂度下的计数排序和基数排序。每种都有各自适用场景及优缺点需要注意选择合适的方法应用于实际开发当中[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值