看几个动画演示 http://atool.org/sort.php http://jsdo.it/norahiko/oxIy/fullscreen
一:冒泡排序 O(n*n)
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
int main()
{
int a[1000],i,j,n,t;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<n-1;i++)
{
for(j=0;j<n-i-1;j++)
{
if(a[j]>=a[j+1])
{
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
二:选择排序 O(n*n)
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
int main()
{
int a[1000],i,j,n,t,p;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<n-1;i++)
{
p=i;
for(j=i+1;j<n;j++)
{
if(a[p]>=a[j])
{
p=j;
}
}
t=a[i];
a[i]=a[p];
a[p]=t;
}
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
三:插入排序 O(nlogn)
n插入排序(Insertion-Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
ll a[10100];
int main()
{
ll n,i,j,c,p;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
for(i=1;i<n;i++)
{
p=i-1;
c=a[i];
while(p>=0&&a[p]>c)
{
a[p+1]=a[p];
p--;
}
a[p+1]=c;
}
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
四:归并排序 O(nlogn)
合并操作(merge),是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
看个例题纯模板
对每一组输入,输出该序列变成有序所需要交换的最少的次数。
Sample Input
5
9
1
0
5
4
3
1
2
3
0
Sample Output
6
0
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
ll a[500001],b[500001];
ll cnt;
void merge_bing(ll frist,ll mid,ll last)
{
ll midd=mid+1;
ll d=0;
ll f=frist;
while(frist<=mid&&midd<=last)
{
if (a[frist]<=a[midd])
b[d++]=a[frist++];
else
{
cnt+=mid-frist+1;
b[d++]=a[midd++];
}
}
while(frist<=mid)
b[d++]=a[frist++];
while(midd<=last)
b[d++]=a[midd++];
for(ll i=0;i<d;i++)
a[f++]=b[i];
}
void mergesort(ll frist,ll last)
{
ll mid=0;
if (frist<last)
{
mid=(frist+last)/2;
mergesort(frist,mid);
mergesort(mid+1,last);
merge_bing(frist,mid,last);
}
}
int main()
{
int n;
while(cin>>n)
{
if(n==0)
break;
ll i,j;
for(i=0;i<n;i++)
cin>>a[i];
cnt=0;
mergesort(0,n-1);
cout<<cnt<<endl;
}
return 0;
}
五:快速排序 O(nlogn)
快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
就是qsort 但是现在一般用sort直接调用函数就好
六:堆排序 O(nlogn)
n堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
void heap_sort( int arr[], int len )
{
int i;
/* 初始化,i从最后一个父结点开始调整 */
for ( i = len / 2 - 1; i >= 0; i-- )
max_heapify( arr, i, len - 1 );
/* 先将第一个元素和已排好元素前一位做交换,再重新调整,直到排序完毕 */
for ( i = len - 1; i > 0; i-- )
{
swap( &arr[0], &arr[i] );
max_heapify( arr, 0, i - 1 );
}
}
void max_heapify( int arr[], int start, int end )
{
/* 建立父结点指标和子结点指标 */
int dad = start;
int son = dad * 2 + 1;
while ( son <= end ) /* 若子结点在指定范围内才做比较 */
{
if ( son + 1 <= end && arr[son] < arr[son + 1] ) /* 先比较两个子结点大小,选择最大的 */
son++;
if ( arr[dad] > arr[son] ) /* 如果父结点大于子结点表示调整完毕,直接跳出函数 */
return;
else { /* 否则交换父子内容再继续子结点和孙结点比较 */
swap( &arr[dad], &arr[son] );
dad = son;
son = dad * 2 + 1;
}
}
}