首页 > 代码库 > 自己写快排模板与C++快排库函数使用

自己写快排模板与C++快排库函数使用

自己写快排模板与C++快排库函数使用


1、自己写快排模板

我理解的快速排序思想原理是:

假定待排序数组的范围是0~N
1、在一个数组中找一个数作为中心点M(可以使用固定位置的数,也可以随机的采用数组中的数)
2、把数组中所有的数与这个中心点进行比较。小于中心点的数移到中心点左边,大于中心点的数移到中心点右边。
3、经过上面两步可以得到由M点所划分的两个数组(一个数组都小于等于M,一个都大于等于M),再对这两个数组递归的进行1、2所示步骤,知道划分的数组大小为0;

快排思想实现的主要的重点难点在于第2步的实现:
1、中心点取在左边,所以重右边J的位置开始判断,I目前的值为Left
2、如果J>=M(中心点的值这里为BASE_Num),则J往左移,反之如果J<M则将数组下标为I的数赋值为J,然后进行第3步
3、I移到下一个位置,如果数组Array[I]的值小于等于M,则I继续往右移,直到Array[i]>M,将Array[J]的值赋为Array[I]
4、重复3、4步 直到I>J



可能我自己的表达不是很清楚,大概的思路和实现就是这样了,可以参考以下文章和代码进行理解。

http://blog.csdn.net/morewindows/article/details/6684558

九度OJ 1196成绩排序  地址:http://ac.jobdu.com/problem.php?pid=1196

#include <stdio.h>

typedef struct
{
	int num;
	int grade;
}STUDENT_INFO_T;

STUDENT_INFO_T  student[101];

//声明一个COMP类型函数指针  以后就可以直接用COMP定义该函数指针 
typedef int (*COMP)(const STUDENT_INFO_T *, const STUDENT_INFO_T *);
 
//比较函数a大于b(a在b后面) 返回1  否则返回0 
int  qCompare(const STUDENT_INFO_T *a, const STUDENT_INFO_T *b)
{
   if(a->grade == b->grade)
	{
		return (a->num - b->num)>0?(1):(0);	
	}
	else 
	{
		return (a->grade - b->grade)>0?(1):(0);
	}  
} 

//快排函数模板 
void quick_sort(STUDENT_INFO_T *p, int l, int r, COMP Comp)
{
	if(l < r)
	{
		int i=l, j=r;
		STUDENT_INFO_T Base_num = p[l];
		
		while(i < j)
		{
			while(i<j && Comp(&p[j],&Base_num))   //pj large than px
	        	j--;
	        if(i < j)
	        {
				p[i++] = p[j];		
			}
			
			while(i<j && !Comp(&p[i],&Base_num))   //pi small than px
				i++;
			if(i < j)
			{
				p[j--] = p[i];	
			}
		}
		p[i] = Base_num;
		quick_sort(p, l, i-1 , Comp);
		quick_sort(p, i+1 , r, Comp);	
	}
}

int main(int argc, char **argv)
{
	int student_count;
	int i;
	
	while(scanf("%d",&student_count)!=EOF)
	{
	
		for(i=0; i<student_count; i++)
		{
	 	   scanf("%d %d",&student[i].num,&student[i].grade);	
		}

		quick_sort(student, 0, student_count-1, qCompare); 
	
		for(i=0; i<student_count; i++)
		{
		    printf("%d %d\n",student[i].num,student[i].grade);	
		}
	}
	return (0);
} 


九度OJ 1061成绩排序 地址:http://ac.jobdu.com/problem.php?pid=1061

#include <stdio.h>

typedef struct
{
	char name[101];
	int age;
	int grade;
}STUDENT_INFO_T;

STUDENT_INFO_T  student[1001];

//声明一个COMP类型函数指针  以后就可以直接用COMP定义该函数指针 
typedef int (*COMP)(const STUDENT_INFO_T *, const STUDENT_INFO_T *);

//与strcmp函数功能一致 
int  my_strcmp(const char *str1, const char *str2)
{
	while(*str1 == *str2)
	{
		if(*str1 == '\0')
		return (0);
		
		str1++;
		str2++;
	}
	
	return (*str1 - *str2);
}
 
//比较函数a大于b(a在b后面) 返回1  否则返回0 
int  qCompare(const STUDENT_INFO_T *a, const STUDENT_INFO_T *b)
{
   if(a->grade == b->grade)
	{
		if(my_strcmp(a->name,b->name) == 0)
		{
			return (a->age - b->age)>0?(1):(0);	
		}
		else 
		{
			return my_strcmp(a->name,b->name)>0?(1):(0);
		}
	}
	else 
	{
		return (a->grade - b->grade)>0?(1):(0);
	}  
} 

//快排函数模板 
void quick_sort(STUDENT_INFO_T *p, int l, int r, COMP Comp)
{
	if(l < r)
	{
		int i=l, j=r;
		STUDENT_INFO_T Base_num = p[l];
		
		while(i < j)
		{
			while(i<j && Comp(&p[j],&Base_num))   //pj large than px
	        	j--;
	        if(i < j)
	        {
				p[i++] = p[j];		
			}
			
			while(i<j && !Comp(&p[i],&Base_num))   //pi small than px
				i++;
			if(i < j)
			{
				p[j--] = p[i];	
			}
		}
		p[i] = Base_num;
		quick_sort(p, l, i-1 , Comp);
		quick_sort(p, i+1 , r, Comp);	
	}
}

int main(int argc, char **argv)
{
	int student_count;
	int i;
	
	while(scanf("%d",&student_count)!=EOF)
	{
	
		for(i=0; i<student_count; i++)
		{
	 	   scanf("%s %d %d",student[i].name,&student[i].age,&student[i].grade);	
		}

		quick_sort(student, 0, student_count-1, qCompare); 
	
		for(i=0; i<student_count; i++)
		{
		    printf("%s %d %d\n",student[i].name,student[i].age,student[i].grade);	
		}
	}
	return (0);
} 


2、C++ 快排库函数使用(特殊情况使用自定义比较函数)

C/C++中有一个快速排序的标准库函数qsort ,在stdlib.h 中声明,其原型为:
void qsort(void *base, int nelem, unsigned int width, int ( * pfCompare)( const void *, const void*));
base 是待排序数组的起始地址
nelem 是待排序数组的元素个数
width 是待排序数组的每个元素的大小(以字节为单位)
pfCompare 是一个函数指针,它指向一个“比较函数”。


qsort 函数的用法规定,“比较函数”的原型应是:
int FunctionName(const void * elem1, const void * elem2);
elem1 和elem,指向待比较的两个元素。
* elem1 和* elem2 就是待比较的两个元素。
该函数必须具有以下行为:
1) 如果 * elem1 应该排在 * elem2 前面,则函数返回值是负整数(任何负整数都行)。
2) 如果 * elem1 和* elem2 哪个排在前面都行,那么函数返回0
3) 如果 * elem1 应该排在 * elem2 后面,则函数返回值是正整数(任何正整数都行)。


一下为c++使用快排库函数的几个必须具备的条件:
1) 关键的函数库: 
#include <stdlib.h>
2) 关键的比较函数(以下为一个简单的例子):

int Comp(const void *p1,const void *p2)

{

    return ( *((int*)p1) )-( *((int*)p2) );
}

3) 关键的调用函数库---快速排序:

qsort(nums,MAX_NUM,sizeof(int),Comp);


下面为各种特殊情况下的比较函数模板:

1)对一维数组排序:

(Element_type是一位数组中存放的数据类型,可以是char, int, float, double, etc)

int Comp(const void *p1,const void *p2 )
{
    return *((Element_type *)p2)-*((Element_type *)p1);
}
int main()
{
    Element_type list[MAX];
    initial(list);

    qsort(list, sizeof(list)/sizeof(Element_type),sizeof(Element_type),Comp);
    //或者qsort(list, MAX,sizeof(Element_type),Comp);

    return 0;
}


2)对字符串排序:

int Comp(const void *p1,const void *p2)
{
    return strcmp((char *)p2),(char *)p1);
}

int main()
{
    char a[MAX1][MAX2];                //这里我用动态数组 char =new 。。。不行
    initial(a);

    qsort(a,lenth,sizeof(a[0]),Comp);  //lenth 为数组a的长度

}


3)按结构体中某个关键字排序(对结构体一级排序):

struct Node
{
    double data;
    int other;

}s[100];

int Comp(const void *p1,const void *p2)
{
    return (*(Node *)p2)->data-(*(Node *)p1)->data;
}

qsort(s,100,sizeof(s[0]),Comp);

4)按结构体中多个关键字排序(对结构体多级排序)[以二级为例]:

struct Node
{
    int x;
    int y;

}s[100];

//按照x从小到大排序,当x相等时按y从大到小排序
int Comp(const void *p1,const void *p2)
{
    struct Node *c = (Node *)p1;
    struct Node *d = (Node *)p2;

    if(c->x != d->x) return c->x-d->x;
    else return d->y - c->y;
}

5)对结构体中字符串进行排序:

struct Node
{
    int data;
    char str[100];

}s[100];

//按照结构体中字符串 str 的字典序排序
int Comp(const void *p1,const void *p2)
{
    return strcmp((*(Node *)p1)->str,(*(Node *)p2)->str);   
}

qsort(s,100,sizeof(s[0],Comp);

6)计算几何中求凸包的Comp:

//以下是我从别人那儿抄来的,暂时还没用过
int Comp(const void *p1,const void *p2)    //重点Comp函数,把除了1点外的所有的点旋转角度排序
{
    struct point *c=(point *)p1;
    struct point *d=(point *)p2;

    if( cacl(*c, *d,p[1]) < 0) 
        return 1;
    else if(!cacl(*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;
}


示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data
{
     int num;
     char name[9];
     int grade;
}student[100009];
 

int CompNum(const void *c,const void *d)   
{
    return (*(data *)c).num-(*(data *)d).num;
}


int CompName(const void *p1,const void *p2)
{
    struct data *c=(data *)p1;
    struct data *d=(data *)p2;

    if(strcmp((*(data *)c).name,(*(data *)d).name)!=0)
        return strcmp((*(data *)c).name,(*(data *)d).name);   //注意括号
    else 
	return (*(data *)c).num-(*(data *)d).num;
}

int CompGrade(const void *p1,const void *p2)
{
  struct data *c=(data *)p1;
  struct data *d=(data *)p2;

  if((*(data *)c).grade!=(*(data *)d).grade)
        return (*(data *)c).grade-(*(data *)d).grade;
  else 
	return (*(data *)c).num-(*(data *)d).num;
}

void Print(struct data student1[],int x)
{
  for(int i=0;i<x;i++)
   printf("%06d %s %d\n",student1[i].num,student1[i].name,student1[i].grade);
}

void NumOrder(struct data student2[],int n)
{
     qsort(student,n,sizeof(student[0]),CompNum);
     Print(student,n);
}

void NameOrder(struct data student2[],int n)
{
     qsort(student,n,sizeof(student[0]),CompName);
     Print(student,n);
}


void GradeOrder(struct data student2[],int n)
{
     qsort(student,n,sizeof(student[0]),CompGrade);
     Print(student,n);
}

int main()
{
 int n,c,count=1;
 while(scanf("%d%d",&n,&c)==2&&n)
 {
  for(int i=0;i<n;i++)
   scanf("%d %s %d",&student[i].num,&student[i].name,&student[i].grade);
  printf("Case %d:\n",count++);
  if(c==1)
  NumOrder(student,n);
  else if(c==2)
  NameOrder(student,n);
  else if(c==3)
  GradeOrder(student,n);
  //for( i=0;i<n;i++)
  // printf("%06d %s %d\n",student[i].num,student[i].name,student[i].grade);

 }
return 0;
}


自己写快排模板与C++快排库函数使用