引入概念:排序稳定性:输入数据的顺序,排序后不能改变。例如,1,2,3,3,5.排序完若第一个3和第二个3互换,则为不稳定。
1.插入排序(稳定)
解释:像打扑克时整理牌时一样,遇到小牌就插在前面比他大的前面,而后面的牌顺次后移;直到处理完最后一张牌。
优点:比冒泡排序只能处理相邻数据更为灵活,适用于数据在一定距离之间排序较为整齐,可以极大提高效率。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
void insertSort(int a[],int n)//插入排序
{
int i,j,v;
for(i=1;i<n;i++)
{
v=a[i];
j=i-1;
while(j>=0&&a[j]>v)
{
a[j+1]=a[j--];
}
a[j+1]=v;
}
}
void printArr(int a[],int n)//遍历数组
{
for(int i=0;i<n;i++)
{
if(i==0)
cout<<a[i];
else
cout<<" "<<a[i];
}
cout<<endl;
}
int main()
{
int a[100],n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
insertSort(a,n);
printArr(a,n);
return 0;
}
2.冒泡排序(稳定)
解释:从后往前,比较相邻的元素,若不符合条件,则调用swap函数交换数据。外循环一次,将最小的放到第一位置,重复到最后一个元素归位。
优点:代码实现较为简单,但处理数据不灵活,只能处理相邻元素。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
void bubbleSort(int a[],int n)//冒泡排序
{
int i,j;
for(i=0;i<n;i++)
for(j=n-1;j>=i+1;j--)
{
if(a[j]<a[j-1])
swap(a[j],a[j-1]);
}
}
void printArr(int a[],int n)//遍历数组
{
for(int i=0;i<n;i++)
{
if(i==0)
cout<<a[i];
else
cout<<" "<<a[i];
}
cout<<endl;
}
int main()
{
int a[100],n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
bubbleSort(a,n);
printArr(a,n);
return 0;
}
3.选择排序(不稳定)
解释:找到一个最小的就替换第一个元素,第二次找第一个之后的最小值,替换第二个元素。。。。
注意:外层循环为0~n-1。
优点:放眼全局,冒泡为局部。由于选择替换的大幅度性,会造成排序的不稳定。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
void selectSort(int a[],int n)//选择排序
{
int i,j,mini;
for(i=0;i<n-1;i++)
{
mini=i;//存储一次循环最小值的下标
for(j=i;j<n;j++)
if(a[j]<a[mini])
mini=j;
swap(a[i],a[mini]);
}
}
void printArr(int a[],int n)//遍历数组
{
for(int i=0;i<n;i++)
{
if(i==0)
cout<<a[i];
else
cout<<" "<<a[i];
}
cout<<endl;
}
int main()
{
int a[100],n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
selectSort(a,n);
printArr(a,n);
return 0;
}
4.希尔排序(稳定)
解释:其实就是将插入排序进行了升级,将间隔由普通插入函数的1,变为了动态的3*n+1,经过一次外循环,他就会整齐一点,直到执行到g=1时,基本已经排的差不多了,so,此排序具有插入排序的优点,又解决了数列不太整齐时普通插入复杂度高的问题。每外循环一次,下一次的内循环就会少很多步骤。是集中了许多优点的排序算法。他的写法就是插入排序和g的取值函数的集合。
缺点:相较于前三种,这个排序写起来略有复杂。
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> G;
int a[10000000];
void insertSort(int a[],int n,int g)//插入排序
{
for(int i=g;i<n;i++)//与普通插入排序一样,只是起点为g.
{
int v=a[i];
int j=i-g;
while(j>=0&&a[j]>v)
{
a[j+g]=a[j];
j-=g;
}
a[j+g]=v;
}
}
void sellSort(int a[],int n)//希尔排序,G数组存储间隔数,如:1,4,13,3*n+1....
{
int h=1;
while(h)
{
if(h>n)
break;
G.push_back(h);
h=3*h+1;
}
for(int i=G.size()-1;i>=0;i--)
{
insertSort(a,n,G[i]);//调用插入排序执行间隔为3*n-1,13,4,1的排序
}
}
void printArr(int a[],int n)//遍历数组
{
for(int i=0;i<n;i++)
{
if(i==0)
cout<<a[i];
else
cout<<" "<<a[i];
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
//insertSort(a,n);
sellSort(a,n);
printArr(a,n);
return 0;
}