C++算法——常见的排序算法例题整合
本文包括:插入排序、冒泡排序、选择排序、归并排序、分割排序、快速排序。
一、插入排序

插入排序流程图
1、题目要求:
请编写一个程序,用插入排序法将包含N个元素的数列A按升序排列。为检验算法的执行过程,请输出各计算步骤的数组(完成输人后的数组,以及每次i自增后的数组)。
2、输入:
在第I行输人定义数组长度的整数N。在第2行输人N个整数,以空格隔开。
3、输出:
输出输出总共有N行。 插入排序法每个计算步骤的中间结果各占用1行。数列的各元素之间空1个空格。请注意,行尾元素后不要有等多余的空格或换行符。
4、数据限制:
限制1≤N≤ 100 0≤A的元素≤1000
5、输入示例:
6
5 2 4 6 1 3
6、输出示例:
5 2 4 6 1 3
2 5 4 6 1 3
2 4 5 6 1 3
2 4 5 6 1 3
1 2 4 5 6 3
1 2 3 4 5 6
7、参考代码:
#include
using namespace std;
int n,j,t,a[105];
int crpx(int n){
for(int i=1;i<=n-1;i++){
t=a[i];
j=i-1;
while((j>=0)&&(a[j]>t)){
a[j+1]=a[j];
j--;
a[j+1]=t;
}
for(int k=0;k<n-1;k++)
cout<<a[k]<<" ";
cout<<a[n-1];
if(i<n-1)
cout<<endl;
}
}
int main(){
cin>>n;
for(int s=0;s<n;s++)
cin>>a[s];
for(int s1=0;s1<n-1;s1++)
cout<<a[s1]<<" ";
cout<<a[n-1];
cout<<endl;
crpx(n);
}
二、冒泡排序

冒泡排序流程图
1、题目要求:
请编写一个程序,读取数列A,利用冒泡排序法将其按升序排列并输出。另外,请报告冒泡排序法执行元素交换的次数。
2、输入:
在第1行输入定义数组长度的整数N。在第2行输入N个整数,以空格隔开。
3、输出:
输出总计2行。 请在第1行输出排序后的数列。数列相邻要素用1个空格隔开。第2行输出元素交换的次数。
4、数据限制:
1≤N≤100 0≤A的元素≤100
5、输入示例:
5
5 3 2 4 1
6、输出示例:
1 2 3 4 5
8
7、参考代码:
#include
using namespace std;
int a[100];
int s=0;
int main()
{
int n;
cin >> n;
for (int i = 0;i < n;i ++)
{
cin >> a[i];
}
for (int i = 0;i < n - 1;i ++)
{
for (int j = 0;j < n - 1 - i;j ++)
{
if (a[j] > a[j + 1])
{
swap(a[j],a[j + 1]);
s++;
}
}
}
for (int i = 0;i < n-1;i ++)
{
cout << a[i] <<" ";
}
cout<<a[n-1];
cout<<endl;
cout<<s;
return 0;
}
三、选择排序

选择排序流程图
1、题目要求:
请编写一个程序,读取数列A,利用选择排序法将其按升序排列并输出。另外,请输出程序实际运行过程中执行交换操作的次数。
2、输入:
在第1行输人定义数组长度的整数N。在第2行输入N个整数,以空格区分。
3、输出:
输出总计2行。 请在第1行输出排序后的数列。数列相邻元素用1个空格隔开。第2行输出交换次数。
4、数据限制:
限制1≤N≤ 100 0≤A的元素≤100
5、输入示例:
6
5 6 4 2 1 3
6、输出示例:
1 2 3 4 5 6
4
7、参考代码:
#include
using namespace std;
int main(){
int a[100];
int n,t=0;
cin >> n;
for(int i = 0; i < n; ++i)
cin >> a[i];
for(int i = 0; i<n-1 ;++i){
int tmpMin = i;
for(int j=i; j<n;++j){
if(a[j]<a[tmpMin])
tmpMin = j;
}
int tmp = a[i];
a[i] = a[tmpMin];
a[tmpMin] = tmp;
if(tmpMin!=i)
t++;
}
for(int i=0;i<n-1;++i)
cout << a[i] << " ";
cout<<a[n-1];
cout<<endl<<t;
return 0;
}
四、归并排序

归并排序流程图
1、题目要求:
请编写一个程序, 利用归并排序法将包含n个整数的数列s按升序排序。另外,请报告共执行了多少次比较运算。
2、输入:
第1行输入n, 第2行输人代表S的n个整数。
3、输出:
在第 1行输出排序完毕的数列S。数列相邻元素用1个空格隔开。在第2行输出比较运算的次数。
4、数据限制:
n≤ 500 000 0≤S的要素≤10的9次方
5、输入示例:
10
8 5 9 2 6 3 7 1 10 4
6、输出示例:
1 2 3 4 5 6 7 8 9 10
34
7、参考代码:
#include
#include
using namespace std;
int tt=0;
void merge(int a[], int *left, int leftcount, int *right,int rightcount)
{
int i, j, k;
i = 0, j =0, k = 0;
while (i < leftcount&&j < rightcount)
{
if (left[i] < right[j])
a[k++] = left[i++];
else
a[k++] = right[j++];
tt++;
}
while (i < leftcount){
a[k++] = left[i++]; tt++; }
while (j < rightcount){
a[k++] = right[j++]; tt++; }
}
void mergeSort(int a[], int n)
{
int mid=n/2;
if (n < 2) return;
int *left = new int[mid];
int *right = new int[n - mid ];
for (int i = 0; i < mid; i++)
left[i] = a[i];
for (int j = mid ; j < n; j++)
right[j-mid] = a[j];
mergeSort(left, mid);
mergeSort(right, n - mid);
merge(a,left,mid,right,n-mid);
delete[] left;
delete[] right;
}
int main()
{
int a[500000];
int length;
cin>>length;
for(int i=0;i<length;i++){
cin>>a[i];
}
mergeSort(a, length);
for (int i = 0; i < length-1; i++)
cout << a[i] <<" ";
cout<<a[length-1];
cout<<endl<<tt;
return 0;
}
五、分割排序

分割排序流程图
1、题目要求:
请根据下述伪代码编写一个程序,输人数列A,执行分割。

请注意,这里的r是数组A末尾元素的下标,进行分割时需以A[r]为基准。
2、输入:
第1行输人表示数列A长度的整数n。第2行输入n个整数,用空格隔开。
3、输出:
在1 行之内输出分割后的数列。数列相邻元素用1个空格隔开。另外,用作分割基准的元素用“[]” 标出。
4、数据限制:
1≤n≤100 000 0≤Ai≤100 000
5、输入示例:
12
13 19 9 5 12 8 7 4 21 2 6 11
6、输出示例:
9 5 8 7 4 2 6 [11] 21 13 19 12
7、参考代码:
#include
using namespace std;
int n,a[100001],d;
int division(int a[],int p,int r){
int x;
x=a[r];
int i=p-1;
for(int j=p;j<r;j++){
if(a[j]<=x){
i++;
swap(a[i],a[j]);
}
}
swap(a[i+1],a[r]);
return i+1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
d=division(a,1,n);
for(int g=1;g<d;g++)
cout<<a[g]<<" ";
cout<<"["<<a[d]<<"]"<<" ";
for(int g1=d+1;g1<n;g1++)
cout<<a[g1]<<" ";
cout<<a[n];
}
六、快速排序

快速排序流程图
1、题目要求:
给n张卡片排序。每张卡片由1个花色(S. H、C. D)和1个数字组成。请根据下述伪代码编写一个程序, 将这些卡片按升序排列。

这里的A为存储卡片的数组,分割中的比较运算以卡片的数字为基准。另外,请报告该程序对输人数据是否有稳定的输出。这里的“稳定输出"是指存在多张数字相同的卡片时,它们输出的顺序与输人的顺序保持一致。
2、输入:
第1 行输人卡片的张数n。接下来n行输入n张卡片。每张卡包含1个代表花色的字母和1个数字(整数)。字母与数字间用1个空格隔开。
3、输出:
第1 行输出该程序的输出是否稳定( Stable或Not stable )。从第2行起,使用与输人相同的格式按顺序输出排序后的卡片(不必输出n)。
4、数据限制:
限制1 ≤n≤100 000
1≤卡片上的数字≤10的9次方
输人中花色和数字全都相同的卡片不超过2张
5、输入示例:
6
D 3
H 2
D 1
S 3
D 2
C 1
6、输出示例:
Not stable
D 1
C 1
D 2
H 2
D 3
S 3
7、参考代码:
#include
using namespace std;
int n,a[100001],a1[100001],a2[100001],d,f,q,t;
char b[100001],b1[100001],b2[100001];
void merge(int l1,int r1 ,int l2,int r2);
int division(int a[],int p,int r){
int x;
x=a[r];
int i=p-1;
for(int j=p;j<r;j++){
if(a[j]<=x){
i++;
swap(a[i],a[j]);
swap(b[i],b[j]);
}
}
swap(a[i+1],a[r]);
swap(b[i+1],b[r]);
return i+1;
}
int quicksort(int a[],int p,int r){
if(p<r){
q=division(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
void split(int left,int right){
int i,j,tem,mid;
i=left;
j=right;
mid=(i+j)/2;
if(i==mid){
merge(i,mid,mid+1,j);
return;}
split(i,mid);
split(mid+1,j);
merge(i,mid,mid+1,j);
}
void merge(int l1,int r1 ,int l2,int r2){
t=l1;
int i=l1,j=l2;
while(i<=r1&&j<=r2){
if(a1[i]<=a1[j]){
a2[t++]=a1[i++];
b2[t-1]=b1[i-1];
}
else{
a2[t++]=a1[j++];
b2[t-1]=b1[j-1];
}
}
while(i<=r1){
a2[t++]=a1[i++];
b2[t-1]=b1[i-1];
}
while(j<=r2){
a2[t++]=a1[j++];
b2[t-1]=b1[j-1];
}
for(int i=l1;i<=r2;i++){
a1[i]=a2[i];
b1[i]=b2[i];
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>b[i]>>a[i];
for(int i=1;i<=n;i++){
a1[i]=a[i];
b1[i]=b[i];
}
quicksort(a,1,n);
split(1,n);
for(int i=1;i<=n;i++){
if(b1[i]!=b[i]){
f=0;
break;
}
else
f=1;
}
if(f==0)
cout<<"Not stable"<<endl;
else if(f==1)
cout<<"Stable"<<endl;
for(int i=1;i<n;i++)
cout<<b[i]<<" "<<a[i]<<endl;
cout<<b[n]<<" "<<a[n];
}