sort函數用法

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.a
ui

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);}

相關文章
相關標籤/搜索