首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

关于qsort()运用有关问题的深思

2012-03-22 
关于qsort()运用问题的深思?我是一名ACMer,菜鸟而已,前几天刚学了最近点对问题,并在杭电上找到相应题目做。

关于qsort()运用问题的深思?
我是一名ACMer,菜鸟而已,前几天刚学了最近点对问题,并在杭电上找到相应题目做。结果本来以为简单的题目,一直WA或

TL,问了很多人也看了很多AC的code, 发现我的思路是完全正确的,但不知道为什么不能AC,唯一不同的就是我是用qsort()排序

,别人是sort();我以前都是用qsort()函数都米错,这应该不会错吧,到最最最最最后绝望的时候就改成了sort()居然AC了,

无限的囧啊,以前都是这么写过来的为什么这次就不行了。纠结!问了很多人依旧不知道问题在于哪里,希望知道的前辈能指

点我一二。在此,非常谢谢!

先贴题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1007

在贴我的4个代码(qsort()中cmp函数有所不同):

第一个AC代码,sort()函数排序:
#include <iostream>  
#include <cstring>  
#include <cstdio>  
#include <cstdlib>  
#include <cmath>  
#include <algorithm>  
using namespace std;  
  
struct node  
{  
  double x, y;  
  int index;  
}px[100002], py[100002];  
  
bool cmpx(const node &a, const node &b)
{
return a.x < b.x;
}

bool cmpy(const node &a, const node &b)
{
return a.y < b.y;
}  
  
double Get_Distance(struct node a, struct node b)  
{  
  return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );  
}  
  
double Closest(int left, int right, struct node py[])  
{  
  double dmin = 99999999;  
  int i, j, k;  
  
  //there are less than three points,then rude  
  if(right - left < 3)  
  {  
  for(i = left; i < right; i++)  
  for(j = i+1; j <= right; j++)  
  {  
  double temp;  
  temp = Get_Distance(px[i], px[j]);  
  if(dmin > temp)  
  dmin = temp;  
  }  
  return dmin;  
  }  
  
  int mid = (right+left)/2;  
  node *pyl = new node[mid - left + 1];  
  node *pyr = new node[right - mid];  
   
  //divide to two part  
  j = k = 0;  
  for(i = 0; i <= right-left; i++)  
  if(py[i].index <= mid)  
  pyl[j++] = py[i];  
  else  
  pyr[k++] = py[i];  
  
  double left_min = Closest(left, mid, pyl);  
  double right_min = Closest(mid+1, right, pyr);  
  
  if(dmin > left_min)  
  dmin = left_min;  
  if(dmin > right_min)  
  dmin = right_min;  
  
  //middle points part  
  k = 0;  
  for(i = 0; i <= right-left; i++)  
  if(fabs(py[i].x - px[mid].x) < dmin)  
  py[k++] = py[i];  
  
  for(i = 0; i < k-1; i++)  
  for(j = i+1; j < k && j < i+7; j++)  
  {  
  double temp;  
  temp = Get_Distance(py[i], py[j]);  
  if(dmin > temp)  
  dmin = temp;  
  }  
  
  delete [] pyl;  
  delete [] pyr;  
  return dmin;  
}  
  
int main()  
{  
  int N, i;  
  
  while(scanf("%d", &N) != EOF)  
  {  
  if(!N)  


  break;  
  
  for(i = 0; i < N; i++)  
  scanf("%lf%lf", &px[i].x, &px[i].y);  
   
  //qsort x and mark position  
  sort(px, px+N, cmpx);
  for(i = 0; i < N; i++)  
  px[i].index = i;  
  
  //copy px[]->py[] and qsort y  
  memcpy(py, px, sizeof(px));  
  sort(py, py+N, cmpx);  
   
  printf("%.2lf\n", Closest(0, N-1, py)/2.0);  
  }  
  
  return 0;  
}  

////////////////////////////////////////////////////////
第二个qsort()排序,TL(超时)代码 ,注意看qsort()中的cmp函数
#include <iostream>  
#include <cstring>  
#include <cstdio>  
#include <cstdlib>  
#include <cmath>  
using namespace std;  
  
struct node  
{  
  double x, y;  
  int index;  
}px[100002], py[100002];  

int CmpX(const void *a, const void *b)
{
return ((struct node *)a)->x > ((struct node *)b)->x ? 1 : -1;
}

int CmpY(const void *a, const void *b)
{
return ((struct node *)a)->y > ((struct node *)b)->y ? 1 : -1;
}
  
double Get_Distance(struct node a, struct node b)  
{  
  return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );  
}  
  
double Closest(int left, int right, struct node py[])  
{  
  double dmin = 99999999;  
  int i, j, k;  
  
  //there are less than three points,then rude  
  if(right - left < 3)  
  {  
  for(i = left; i < right; i++)  
  for(j = i+1; j <= right; j++)  
  {  
  double temp;  
  temp = Get_Distance(px[i], px[j]);  
  if(dmin > temp)  
  dmin = temp;  
  }  
  return dmin;  
  }  
  
  int mid = (right+left)/2;  
  node *pyl = new node[mid - left + 1];  
  node *pyr = new node[right - mid];  
   
  //divide to two part  
  j = k = 0;  
  for(i = 0; i <= right-left; i++)  
  if(py[i].index <= mid)  
  pyl[j++] = py[i];  
  else  
  pyr[k++] = py[i];  
  
  double left_min = Closest(left, mid, pyl);  
  double right_min = Closest(mid+1, right, pyr);  
  
  if(dmin > left_min)  
  dmin = left_min;  
  if(dmin > right_min)  
  dmin = right_min;  
  
  //middle points part  
  k = 0;  
  for(i = 0; i <= right-left; i++)  
  if(fabs(py[i].x - px[mid].x) < dmin)  
  py[k++] = py[i];  
  
  for(i = 0; i < k-1; i++)  
  for(j = i+1; j < k && j < i+7; j++)  
  {  
  double temp;  
  temp = Get_Distance(py[i], py[j]);  
  if(dmin > temp)  


  dmin = temp;  
  }  
  
  delete [] pyl;  
  delete [] pyr;  
  return dmin;  
}  
  
int main()  
{  
  int N, i;  
  
  while(scanf("%d", &N) != EOF)  
  {  
  if(!N)  
  break;  
  
  for(i = 0; i < N; i++)  
  scanf("%lf%lf", &px[i].x, &px[i].y);  
  //qsort x and mark position  
  qsort(px, N, sizeof(px[0]), CmpX);  
  for(i = 0; i < N; i++)  
  px[i].index = i;  
  
  //copy px[]->py[] and qsort y  
  memcpy(py, px, sizeof(px));  
  qsort(py, N, sizeof(py[0]), CmpY);  
   
  printf("%.2lf\n", Closest(0, N-1, py)/2.0);  
  }  
  
  return 0;  
}  


第三个,qsort(),WA(错误)代码:(其他地方一样的,就是qsort()中cmp函数不同)
int CmpX(const void *a, const void *b)  
{  
  return ((struct node *)a)->x > ((struct node *)b)->x;  
}  
  
int CmpY(const void *a, const void *b)  
{  
  return ((struct node *)a)->y > ((struct node *)b)->y;  


第四个,qsort(),AC(成功)代码:(其他地方一样,就是cmp函数不同)
int CmpX(const void *a, const void *b)  
{  
  if( ((struct node *)a)->x < ((struct node *)b)->x )  
  return -1;  
  else  
  if( ((struct node *)a)->x == ((struct node *)b)->x )  
  return 0;  
  else  
  return 1;  
}  
  
int CmpY(const void *a, const void *b)  
{  
  if( ((struct node *)a)->y < ((struct node *)b)->y )  
  return -1;  
  else  
  if( ((struct node *)a)->y == ((struct node *)b)->y )  
  return 0;  
  else  
  return 1;  
}  

///////////////////////////////////////////////////////////////////////////
  我以前都是第2个 或 第3个这么写的cmp函数排序都可以,但是这次 必须要把cmp的三种情况都写全,

才能够AC。  
/////////////////////////////////////////////////////////////////////////////
我看了MSDN中qsort()如下:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

compare( (void *) elem1, (void *) elem2 );

The routine must compare the elements, then return one of the following values:

Return Value Description 
< 0 elem1 less than elem2 
0 elem1 equivalent to elem2 
> 0 elem1 greater than elem2 

////////////////////////////////////////////////////////////
  虽然cmp中确实是三种情况,但是我们平时写的时候都不是写全的,一样能达到

从小到大的排序。见以下资料:
一、对int类型数组排序

int num[100];
int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}
qsort(num,100,sizeof(num[0]),cmp);
二、对char类型数组排序(同int类型)
char word[100];
int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
}
qsort(word,100,sizeof(word[0]),cmp);
三、对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);
四、对结构体一级排序  
struct Sample


{
double data;
int other;
}s[100]
//按照data的值从小到大将结构体排序
int cmp( const void *a ,const void *b)
{
return (*(Sample *)a).data > (*(Sample *)b).data ? 1 : -1;
}
qsort(s,100,sizeof(s[0]),cmp);
五、对结构体二级排序
struct Sample
{
int x;
int y;
}s[100];

//按照x从小到大排序,当x相等时按照y从大到小排序
int cmp( const void *a , const void *b )
{
struct Sample *c = (Sample *)a;
struct Sample *d = (Sample *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}
qsort(s,100,sizeof(s[0]),cmp);
六、对字符串进行排序
struct Sample
{
int data;
char str[100];
}s[100];

//按照结构体中字符串str的字典顺序排序
int cmp ( const void *a , const void *b )
{
return strcmp( (*(Sample *)a)->str , (*(Sample *)b)->str );
}
qsort(s,100,sizeof(s[0]),cmp);

附加一个完整点的代码,对字符串二维数组排序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[2001][1001];
int cmp(const void *a, const void *b){
  return strcmp((char *)a,(char *)b);
}
int main(){
  int i,n;
  scanf("%d",&n);
  getchar();
  for(i=0;i<n;i++) gets(s[i]);
  qsort(s,n,1001*sizeof(char),cmp);
  for(i=0;i<n;i++) puts(s[i]);
  return 0;
}

//////////////////////////////////////////////////////////
  我第二个代码 和 第三个代码在以前资料中有写到,但是 我用在此题目中不行。

我通过输入点实例,输出排序后的点,发现点的排序米问题(测试的点有10几个)。

有群友说可能是duoble类型的精确度的问题,所以此时的cmp函数必须把三种情况写全,

有些说可能是此题目的数据bug问题。。。。囧,我都糊涂了,弄得我以后都不敢用qsort()

到底是什么原因,导致这样的情况,希望知道的前辈指点一二。

在此非常感谢!

[解决办法]
qsort的比较函数是直接作为函数指针处理的所以慢。sort是模板函数,所以比较函数很容易inline优化深度要比qsort高。另外qsort是纯quicksort,sort是优化的quicksort,quicksort递归次数过多的时候会改用heapsort,所以实际时间复杂度更接近O(NlogN)
[解决办法]

探讨

qsort的比较函数是直接作为函数指针处理的所以慢。sort是模板函数,所以比较函数很容易inline优化深度要比qsort高。另外qsort是纯quicksort,sort是优化的quicksort,quicksort递归次数过多的时候会改用heapsort,所以实际时间复杂度更接近O(NlogN)

[解决办法]
探讨

引用:

qsort的比较函数是直接作为函数指针处理的所以慢。sort是模板函数,所以比较函数很容易inline优化深度要比qsort高。另外qsort是纯quicksort,sort是优化的quicksort,quicksort递归次数过多的时候会改用heapsort,所以实际时间复杂度更接近O(NlogN)


嗯谢谢 那你的意思就是说,我……

热点排行