6種排序模板
看幾個動畫演示 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;
}
}
}