自己写快排模板与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;
}

时间: 2024-10-14 04:11:50

自己写快排模板与C++快排库函数使用的相关文章

快排模板

#include<iostream> #include<cstdio> #include<cmath> using namespace std; void quicksort(int a[],int left,int right) { int i,j,base; i=left; j=right; base=a[(i+j)/2]; while (i<=j){ while (a[i]<base) i++; while (a[j]>base) j--; if

快排 [模板]

快排 [模板] #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int a[N]; void quick_sort(int l,int r,int q[]){ if(l >= r) return ;// 递归边界 int base = q[l + r >> 1],i = l - 1,j = r + 1;// 基准设置为中点,先把两个指针扩两边 while(i < j) {// 指

63.如何对单链表进行快排?和数组快排的分析与对比[quicksort of array and linked list]

[本文链接] http://www.cnblogs.com/hellogiser/p/quick-sort-of-array-and-linked-list.html [题目] 单链表的特点是:单向.设头结点位head,则最后一个节点的next指向NULL.如果只知道头结点head,请问怎么将该链表排序? [分析] 对于数组的快排:有2种方式. (1)指针相向移动:一个指针i指向头,一个指针j指向尾,然后两个指针相向运动并按一定规律交换值,最后找到一个支点p使得支点左边的值小于支点,支点右边的值

hdu 1465 不容易系列之一(错排模板)

不容易系列之一 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 20941    Accepted Submission(s): 8937 Problem Description 大家常常感慨,要做好一件事情真的不容易,确实,失败比成功容易多了!做好"一件"事情尚且不易,若想永远成功而总从不失败,那更是难上加难了,就像花钱总是比

上网爱快?EasyRadius FOR 爱快V2接口测试版正式推出,欢迎广大爱迷们测试噢

…… …… 有些人问:为什么上面要打省略号?那些因为此处省略无数字,但是我还是要和大伙们谈谈EasyRadius支持爱快的故事 早在2013年的时候,我们内部就有发布爱快接口,但是由于当时V1的爱快,各方面的不稳定(CPU高,不算流控的流控,还有啥叫负载?),所以迟迟未对外发布接口 2014年,我们未对爱快特别关注,随着爱快的进步及爱快市场部与我们取得的联系,我们决定发布爱快V2接口(不支持V1版本). 下了这个决定以后,当晚就在公司对爱快的接口进行升级,出了V2版的接口.后面把他交附前台工作负

三种排序:快排,归并,堆排

转自:http://www.cnblogs.com/LUO77/p/5798149.html (一)快排 快排考的是最多次的.之前看大神写的算法很简单,思想也很好.就一直用他的思想去思考快排了.挖坑法. 拿走第一个元素作为标兵元素,即挖坑,然后从后面找一个比它小的填坑,然后又形成一个坑,再从前面找一个比标兵大的填坑,又形成一个坑.……最后一个坑填入标兵就好. 然后就是递归了.再在标兵左边排序,右边排序. 1 void QSort(int* num, int start, int end) { 2

快排,随机快排,双路快排,三路快排的理解

再讲快排之前,首先对于任何一个数组,无论之前是多么杂乱,排完之后是不是一定存在一个数作为分界点(也就是所谓的支点),在支点左边全是小于等于这个支点的,然后在这个支点右边的全是大于等于这个支点的,快排过程就是寻找这个支点过程 先看普通的快排(普通单路快排) 代码如下 let findIndex = (arr, l, len) => { let par = arr[l], j = l for (let i = l + 1; i <= len; i++) { if (arr[i] < par)

代码示例:一些简单技巧优化JavaScript编译器工作详解,让你写出高性能运行的更快JavaScript代码

告诉你一些简单的技巧来优化JavaScript编译器工作,从而让你的JavaScript代码运行的更快.尤其是在你游戏中发现帧率下降或是当垃圾回收器有大量的工作要完成的时候. 单一同态: 当你定义了一个两个参数的函数,编译器会接受你的定义,如果函数参数的类型.个数或者返回值的类型改变编译器的工作会变得艰难.通常情况下,单一同态的数据结构和个数相同的参数会让你的程序会更好的工作. function example(a, b) { // 期望a,b都为数值类型 console.log(++a * +

探索C/C++大数快(自然数)模板

本文fcbruce个人原创整理.转载请注明出处http://blog.csdn.net/u012965890/article/details/40432511,谢谢. 我们知道在C/C++中int型可处理-2^31~2^31-1(32位及以上编译器),long long型可处理-2^63~2^63-1的数据,这实际上是非常有限的.在非常多情况下.我们往往会处理范围更大的数据. Java中有BigInteger类,python中想要多大就有多大(取决于内存),可是C/C++就显得有些乏力,这时候我