sort函數的用法node
作ACM題的時候,排序是一種常常要用到的操做。若是每次都本身寫個冒泡之類的O(n^2)排序,不但程序容易超時,並且浪費寶貴的比賽時間,還頗有可能寫錯。STL裏面有個sort函數,能夠直接對數組排序,複雜度爲n*log2(n)。使用這個函數,須要包含頭文件。
這個函數能夠傳兩個參數或三個參數。第一個參數是要排序的區間首地址,第二個參數是區間尾地址的下一地址。也就是說,排序的區間是[a,b)。簡單來講,有一個數組int a[100],要對從a[0]到a[99]的元素進行排序,只要寫sort(a,a+100)就好了,默認的排序方式是升序。
拿我出的「AC的策略」這題來講,須要對數組t的第0到len-1的元素排序,就寫sort(t,t+len);
對向量v排序也差很少,sort(v.begin(),v.end());
排序的數據類型不侷限於整數,只要是定義了小於運算的類型均可以,好比字符串類string。
若是是沒有定義小於運算的數據類型,或者想改變排序的順序,就要用到第三參數——比較函數。比較函數是一個本身定義的函數,返回值是bool型,它規定了什麼樣的關係纔是「小於」。想把剛纔的整數數組按降序排列,能夠先定義一個比較函數cmp
bool cmp(int a,int b)
{
return a>b;
}
排序的時候就寫sort(a,a+100,cmp);數組
假設本身定義了一個結構體node
struct node{
int a;
int b;
double c;
}
有一個node類型的數組node arr[100],想對它進行排序:先按a值升序排列,若是a值相同,再按b值降序排列,若是b還相同,就按c降序排列。就能夠寫這樣一個比較函數:函數
如下是代碼片斷:
bool cmp(node x,node y)
{
if(x.a!=y.a) return x.aui
if(x.b!=y.b) return x.b>y.b;
return return x.c>y.c;
} 排序時寫sort(arr,a+100,cmp);指針
qsort(s[0],n,sizeof(s[0]),cmp);
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}blog
1、對int類型數組排序 排序
int num[100]; 字符串
Sample: get
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
} string
qsort(num,100,sizeof(num[0]),cmp);
2、對char類型數組排序(同int類型)
char word[100];
Sample:
int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
}
qsort(word,100,sizeof(word[0]),cmp);
3、對double類型數組排序(特別要注意)
double in[100];
int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}
qsort(in,100,sizeof(in[0]),cmp);
4、對結構體一級排序
struct In
{
double data;
int other;
}s[100]
//按照data的值從小到大將結構體排序,關於結構體內的排序關鍵數據data的類型能夠不少種,參考上面的例子寫
int cmp( const void *a ,const void *b)
{
return ((In *)a)->data - ((In *)b)->data ;
}
qsort(s,100,sizeof(s[0]),cmp);
5、對結構體
struct In
{
int x;
int y;
}s[100];
//按照x從小到大排序,當x相等時按照y從大到小排序
int cmp( const void *a , const void *b )
{
struct In *c = (In *)a;
struct In *d = (In *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
6、對字符串進行排序
struct In
{
int data;
char str[100];
}s[100];
//按照結構體中字符串str的字典順序排序
int cmp ( const void *a , const void *b )
{
return strcmp( ((In *)a)->str , ((In *)b)->str );
}
qsort(s,100,sizeof(s[0]),cmp);
7、計算幾何中求凸包的cmp
int cmp(const void *a,const void *b) //重點cmp函數,把除了1點外的全部點,旋轉角度排序
{
struct point *c=(point *)a;
struct point *d=(point *)b;
if( calc(*c,*d,p[1]) < 0) return 1;
else if( !calc(*c,*d,p[1]) && dis(c->x,c->y,p[1].x,p[1].y) < dis(d->x,d->y,p[1].x,p[1].y)) //若是在一條直線上,則把遠的放在前面
return 1;
else return -1;
}
** 關於快排函數的一些說明 **
qsort,包含在stdlib.h頭文件裏,函數一共四個參數,沒返回值.一個典型的qsort的寫法以下
qsort(s,n,sizeof(s[0]),cmp);
其中第一個參數是參與排序的數組名(或者也能夠理解成開始排序的地址,由於能夠寫&s[i]
這樣的表達式,這個問題下面有說明); 第二個參數是參與排序的元素個數; 第三個三數是
單個元素的大小,推薦使用sizeof(s[0])這樣的表達式,下面也有說明 :) ;第四個參數就是
不少人以爲很是困惑的比較函數啦,關於這個函數,還要說的比較麻煩...
咱們來討論cmp這個比較函數(寫成cmp是個人我的喜愛,你能夠隨便寫成什麼,好比qcmp什麼
的).典型的cmp的定義是
int cmp(const void *a,const void *b);
返回值必須是int,兩個參數的類型必須都是const void *,那個a,b是我隨便寫的,我的喜愛.
假設是對int排序的話,若是是升序,那麼就是若是a比b大返回一個正值,小則負值,相等返回
0,其餘的依次類推,後面有例子來講明對不一樣的類型如何進行排序.
在函數體內要對a,b進行強制類型轉換後才能獲得正確的返回值,不一樣的類型有不一樣的處理
方法.具體狀況請參考後面的例子.
** 關於快排的一些小問題 **
1.快排是不穩定的,這個不穩定一個表如今其使用的時間是不肯定的,最好狀況(O(n))和最
壞狀況(O(n^2))差距太大,咱們通常說的O(nlog(n))都是指的是其平均時間.
2.快排是不穩定的,這個不穩定表如今若是相同的比較元素,可能順序不同,假設咱們有
這樣一個序列,3,3,3,可是這三個3是有區別的,咱們標記爲3a,3b,3c,快排後的結果不必定
就是3a,3b,3c這樣的排列,因此在某些特定場合咱們要用結構體來使其穩定(No.6的例子就
是說明這個問題的)
3.快排的比較函數的兩個參數必須都是const void *的,這個要特別注意,寫a和b只是個人
我的喜愛,寫成cmp也只是個人我的喜愛.推薦在cmp裏面從新定義兩個指針來強制類型轉換,
特別是在對結構體進行排序的時候
4.快排qsort的第三個參數,那個sizeof,推薦是使用sizeof(s[0])這樣,特別是對結構體,
每每本身定義2*sizeof(int)這樣的會出問題,用sizeof(s[0)既方便又保險
5.若是要對數組進行部分排序,好比對一個s[n]的數組排列其從s[i]開始的m個元素,只須要
在第一個和第二個參數上進行一些修改:qsort(&s[i],m,sizeof(s[i]),cmp);
** 標程,舉例說明 **
No.1.手工實現QuickSort
#include <stdio.h>
int a[100],n,temp;
void QuickSort(int h,int t)
{
if(h>=t) return;
int mid=(h+t)/2,i=h,j=t,x;
x=a[mid];
while(1)
{
while(a[i]<x) i++;
while(a[j]>x) j--;
if(i>=j) break;
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
a[mid]=a[j];
a[j]=x;
QuickSort(h,j-1);
QuickSort(j+1,t);
return;
}
int main()
{
int i;
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%d",&a[i]);
QuickSort(0,n-1);
for(i=0;i<n;i++) printf("%d ",a[i]);
return(0);
}
No.2.最多見的,對int數組排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int s[10000],n,i;
int cmp(const void *a, const void *b)
{
return(*(int *)a-*(int *)b);
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%d",&s[i]);
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%d ",s[i]);
return(0);
}
No.3.對double型數組排序,原理同int
這裏作個註釋,原本是由於要判斷若是a==b返回0的,可是嚴格來講,兩個double數是不可能相等的,只能說fabs(a-b)<1e-20之類的這樣來判斷,因此這裏只返回了1和-1
#include <stdio.h>
#include <stdlib.h>
double s[1000];
int i,n;
int cmp(const void * a, const void * b)
{
return((*(double*)a-*(double*)b>0)?1:-1);
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%lf",&s[i]);
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%lf ",s[i]);
return(0);
}
No.4.對一個字符數組排序.原理同int
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char s[10000],i,n;
int cmp(const void *a,const void *b)
{0
return(*(char *)a-*(char *)b);
}
int main()
{
scanf("%s",s);
n=strlen(s);
qsort(s,n,sizeof(s[0]),cmp);
printf("%s",s);
return(0);
}
No.5.對結構體排序
註釋一下.不少時候咱們都會對結構體排序,好比校賽預選賽的那個櫻花,通常這個時候都在
cmp函數裏面先強制轉換了類型,不要在return裏面轉,我也說不清爲何,可是這樣程序會
更清晰,而且絕對是沒錯的. 這裏一樣請注意double返回0的問題
#include <stdio.h>
#include <stdlib.h>
struct node
{
double date1;
int no;
} s[100];
int i,n;
int cmp(const void *a,const void *b)
{
struct node *aa=(node *)a;
struct node *bb=(node *)b;
return(((aa->date1)>(bb->date1))?1:-1);
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
s[i].no=i+1;
scanf("%lf",&s[i].date1);
}
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%d %lf\n",s[i].no,s[i].date1);
return(0);
}
No.6.對結構體排序.加入no來使其穩定(即data值相等的狀況下按原來的順序排)
#include <stdio.h>
#include <stdlib.h>
struct node
{
double date1;
int no;
} s[100];
int i,n;
int cmp(const void *a,const void *b)
{
struct node *aa=(node *)a;
struct node *bb=(node *)b;
if(aa->date1!=bb->date1)
return(((aa->date1)>(bb->date1))?1:-1);
else
return((aa->no)-(bb->no));
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
s[i].no=i+1;
scanf("%lf",&s[i].date1);
}
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%d %lf\n",s[i].no,s[i].date1);
return(0);
}
No.7.對字符串數組的排序(char s[][]型)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char s[100][100];
int i,n;
int cmp(const void *a,const void *b)
{
return(strcmp((char*)a,(char*)b));
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++) scanf("%s",s[i]);
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%s\n",s[i]);
return(0);
}
No.8.對字符串數組排序(char *s[]型)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *s[100];
int i,n;
int cmp(const void *a,const void *b)
{
return(strcmp(*(char**)a,*(char**)b));
}
int main()
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
s[i]=(char*)malloc(sizeof(char*));
scanf("%s",s[i]);
}
qsort(s,n,sizeof(s[0]),cmp);
for(i=0;i<n;i++) printf("%s\n",s[i]);
return(0);}