C语言快排函数详解
- 格式:pdf
- 大小:92.28 KB
- 文档页数:9
c里面快排函数快排函数是一种高效的排序算法,常用于对大量数据进行排序。
它的基本思想是选择一个基准元素,将数组分成两个部分,一部分比基准元素小,一部分比基准元素大,然后对这两部分分别进行排序。
具体实现时,可以采用递归的方式,不断对子数组进行快排操作,直到排序完成。
在C语言中,快排函数可以通过以下代码实现:```void quick_sort(int arr[], int left, int right) {int i, j, pivot, temp;if (left < right) {pivot = left;i = left;j = right;while (i < j) {while (arr[i] <= arr[pivot] && i < right)i++;while (arr[j] > arr[pivot])j--;if (i < j) {temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}temp = arr[pivot];arr[pivot] = arr[j];arr[j] = temp;quick_sort(arr, left, j - 1);quick_sort(arr, j + 1, right);}}```在该函数中,left和right表示数组的左右边界,即待排序的数组下标范围。
pivot表示基准元素的下标,初始值为left。
使用i 和j两个指针分别从左到右和从右到左扫描数组,将比基准元素大和小的元素交换位置,直到i和j相遇。
最后将基准元素和j指针所指的元素交换位置。
然后递归对左右两个子数组进行快排操作,直到排序完成。
快速排序(C语言)快速排序是冒泡排序的一种改进,主要的算法思想是在待排序的n个数据中取第一个数据作为基准值,将所有记录分为3组,使第1组中各数据值均小于或等于基准值,第2组做基准值的数据,第3组中各数据均大于或等于基准值。
快速排序是排序算法中,平均时间复杂度为O(n*logn)的一种算法,其实现需要先解决这样的一个问题,对一个序列A[1],A[2],A[3].......A[N],调整序列中元素的位置,使得A[1](原序列中的第一个元素,下同)的左侧所有元素都不超过A[1],右侧所有元素都大于A[1],例如对序列{5,3,9,6,4,1}来说,调整后变为{3,1,4,5,9,6}这样就让A[1]=5,左侧的所有元素,不超过它,右侧的所有元素都大于它。
排序思想1.快排是对冒泡排序的一种改进,在快速排序中,元素的比较和移动是从两端向中间进行的,关键码较大的元素一次就能从前面移动到后面,关键码较小的元素一次就能从后面移动到前面,元素移动距离的较远,从而减少了总的比较次数和移动次数2.快速排序是基于分治法设计的,其分治策略是:①、划分:选定一个元素作为轴值,以轴值为基准将整个序列划分为两个子序列。
轴值的位置在划分的过程中确定,并且前一个子序列的元素均小于或者等于轴值,后一个子序列的元素大于或者等于轴值②、求解子问题:分别对划分后的每一个子序列递归处理③、合并:由于对子序列的排序是就地进行的,所以合并并不需要执行任何操作排序方法1.选择轴值,一般是选取第一个元素的关键码。
有一个快排的最坏情况就是如果待排序元素是正序或者逆序,就会将除轴值以外的元素分到轴值的一边。
2.划分①、设置划分区间:i=first,j=end②、执行右侧扫描,直到r[j]小于轴值,将r[j]与r[i]交换,i++③、执行左侧扫描,直到r[i]大于轴值,将r[i]与r[j]交换,j–④、重复二到三直到i=j,确定看轴值的所在位置,返回该位置。
c语⾔快速排序的库函数整理这些库函数都是在平时编程中经常调⽤的快排函数View Code以下所介绍的所有排序都是从⼩到⼤排序快速排序的库函数都包含在头⽂件名为<stdlib.h>中<1>对int型数组排序int num[100];int cmp(const void *a,const void *b){return *(int *)a-*(int *)b;}int main(){......qsort(num,100,sizeof(num[0]),cmp);return0;}<2>对char型数组排序char st[100];int cmp(const void *a,const void *b){return *(char *)a-*(char *)b;}int main(){......qsort(st,100,sizeof(st[0]),cmp);return0;}<3>对double型数组排序double f[100];int cmp(const void *a,const void *b){return ((*(double *)a-*(double *)b>0)?1:-1);}int main(){......qsort(f,100,sizeof(f[0]),cmp);return0;}<4>对结构体排序struct node{double data;int flag;}f[100];int cmp(const void *a,const void *b){return (((struct node *)a)->data>((struct node *)b)->data?1:-1);}int main(){......qsort(f,100,sizeof(f[0]),cmp);return0;}<5>对结构体的⼆级排序struct node{double data;int flag;}f[100];int cmp(const void *a,const void *b){if(((struct node *)a)->data != ((struct node *)b)->data)return (((struct node *)a)->data > ((struct node *)b)->data?1:-1);elsereturn (((struct node *)a)->flag-((struct node *)b)->flag);}int main(){......qsort(f,100,sizeof(f[0]),cmp);return0;}<6>对字符串数组的排序int st[100];int cmp(const void *a,const void *b){return strcmp((char *)a,(char *)b);//根据字典序进⾏⽐较排序}int main(){......qsort(st,100,sizeof(st[0]),cmp);return0;}<7>对指针数组的排序char *s[100];//定义⼀个指针的数组int cmp(const void *a,const void *b){return (strcmp(*(char**)a,*(char**)b));//这⾥⽤char**表⽰指针的指针}int main(){......qsort(s,100,sizeof(s[0]),cmp);return0;}。
快速排序c语言首先我们要对一组数据进行排序:1.在数组中选一个基准数(通常为数组第一个,黄圈圈标记了);2.将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边,怎么移动,后面说;3.对于参考号左右两侧的数组,连续重复上述两个过程,直到每个子集只有一个元素,即全部有序。
好了,咱们开始吧!快速排序需要两个哨兵,i 和 j,分别指向数组的头和尾。
接下来就要进行移动。
我们通常选择第一个元素作为基准数,去移动数组元素,使其达到这个基准数的左边都是小于它的,右边都是大于它的。
开始移动 i 和 j , i 和 j 是交互移动的,这里我们需要先移动 j,这是为甚呢,原因是先移动 j,等到这一行移动结束,i 的下一个就是 j 的时候,我们先移动 j ,可以避免将数据移动错误,后面会有体会。
当移动 j 时,就开始比较 j 是否比基准数大,如果大于或者等于就 j–,否则再看 i,如果 i 小于等于6,则i++ 再与基准数进行比较,否则 i 就要与 j指向的值互换,我们拿上面那个看第一步:看j的值比6小,然后看i,i的值是6,所以i++,后面 i继续++,4,3,5都比6小,所以 i 就移动到了7下面。
到这里,j 所指向的值要与 i 所指向的值互换。
互换完成,后面在比较 j 所指向的位置是否比基准数大,如果大就j–;这里 7 , 9 ,都比6大,所以j–,进行两次,j 就到达了4的下面。
4比6小,所以要再看 i,i 指向0,所以 i需要 i++,到 1,1也小于6, 所以 i 还需要++,到这里 i 就和j指向同一个数4,然后 i = j 了,不能够满足条件,所以就要进行互换,将 i 指向的数,与基准数互换,这一轮比较就结束了,到这里,基准数6的左边都比6小,右边都比6大。
后面还是按照这个来分别再基准数6的左右开始比较。
后面就找这样来,在左右两边再各自将第一个元素作为基准数进行排序。
以此类推,就好了,我把代码贴上。
数组排序c语言数组排序方法在C语言中,可以使用多种排序算法对数组进行排序。
常见的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等。
下面将详细介绍这些排序算法的原理、实现以及时间复杂度。
1. 冒泡排序(Bubble Sort):冒泡排序是一种简单的排序算法,其基本思想是重复地在相邻的元素之间进行比较和交换,将最大的元素逐渐“浮”到数组的尾部。
具体实现过程如下:cvoid bubbleSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {for (int j = 0; j < n-1-i; j++) {if (arr[j] > arr[j+1]) {交换相邻元素int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}}冒泡排序的时间复杂度为O(n^2),其中n为数组长度。
2. 选择排序(Selection Sort):选择排序也是一种简单的排序算法,其基本思想是每次从未排序的部分中选取最小(或最大)的元素,放到已排序部分的末尾。
具体实现过程如下:cvoid selectionSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {int minIndex = i;for (int j = i+1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}将最小元素交换到已排序部分的末尾int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}选择排序的时间复杂度为O(n^2)。
3. 插入排序(Insertion Sort):插入排序的基本思想是将数组分为已排序和未排序两部分,每次从未排序部分选择一个元素,插入到已排序部分的正确位置。
c语言中快速排序函数快速排序是C语言中最常用的排序算法之一。
它的目标是将一个数组按照从小到大排序。
快速排序本质上是一个递归排序算法,它将一个大问题分解成了许多小问题。
下面,我们将逐步讲解C语言中快速排序函数的实现细节。
1. 算法原理快速排序算法基于分治的思想。
具体来说,它的基本思路是选择一个元素,称为“主元”,然后将数组中小于主元的元素移动到主元左边,大于主元的元素移动到主元右边。
这种分组操作称为“分区”。
随后,在主元左边和右边分别执行递归排序,直到全部元素有序。
2. 算法实现首先,我们应该为快速排序函数提供两个参数:数组名和数组大小。
```cvoid quicksort(int *arr, int size) { ... }```在函数内部,我们需要选择主元以及实现分区。
下面是一个常用的主元选择方法:选取数组中间的元素。
```cint pivot = arr[size/2];```然后,我们需要将数组分为小于主元和大于主元的两部分。
具体来说,我们可以使用两个“指针”,一个指向数组的头部,一个指向尾部。
从头部开始,如果元素比主元小,就向右移动指针;从尾部开始,如果元素比主元大,就向左移动指针。
当两个指针相遇时,整个数组就被分成了两个部分。
```cint left = 0, right = size - 1;while (left <= right) {while (arr[left] < pivot)left++;while (arr[right] > pivot)right--;if (left <= right) {int temp = arr[left];arr[left] = arr[right];arr[right] = temp;left++;right--;}}```最后,我们需要分别对两个部分递归排序。
```cif (right > 0)quicksort(arr, right+1);if (left < size-1)quicksort(&arr[left], size-left);```3. 示例代码为了完整地展示快速排序函数的实现细节,下面是一段完整的示例代码:```c#include <stdio.h>void quicksort(int *arr, int size) {if (size <= 1)return;int pivot = arr[size/2];int left = 0, right = size - 1;while (left <= right) {while (arr[left] < pivot)left++;while (arr[right] > pivot)right--;if (left <= right) {int temp = arr[left];arr[left] = arr[right];arr[right] = temp;left++;right--;}}if (right > 0)quicksort(arr, right+1);if (left < size-1)quicksort(&arr[left], size-left);}int main() {int arr[] = {4, 7, 1, 3, 9, 2, 8, 5, 6};int size = sizeof(arr) / sizeof(int);quicksort(arr, size);printf("Sorted array: ");for (int i = 0; i < size; i++)printf("%d ", arr[i]);printf("\n");return 0;}```4. 总结快速排序是C语言中最常用的排序算法之一。
c语言快排函数详解c语言快排函数详解int cmp(const void *a, const void *b)返回正数就是说cmp 传入参数第一个要放在第二个后面, 负数就是传入参数第一个要放第二个前面, 如果是 0, 那就无所谓谁前谁后..下面就把snoopy曾经写的介绍qsort的完整版贴出来好了,我想有与我一样经历的朋友也可以弄懂的:很多人问这个东西.我以前也看了好久,今天翻到以前学快排的时候写的练习code,基本上能覆盖绝大部分用法了.里面有很多地方没判断相等的情况,按道理来说相等情况下应该返回0的,这个请看代码的时候注意.我尽量保证代码不出错了.下面的这些说明和问题都是个人原创,没查什么资料,所以不保证其完全正确性,在此表示个人不对出现的问题负任何责任,大家WA了或者干吗的不要怪我,不过至少目前来说我用起来是没问题的 :)** 关于快排函数的一些说明 **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#includeint 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]<="" p="">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<="" scanf("%d",&a[i]);="">for(i=0;ireturn(0);}No.2.最常见的,对int数组排序#include#include#includeint 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<="">qsort(s,n,sizeof(s[0]),cmp);for(i=0;ireturn(0);}No.3.对double型数组排序,原理同int这里做个注释,本来是因为要判断如果a==b返回0的,但是严格来说,两个double数是不可能相等的,只能说fabs(a-b)<1e-20之类的这样来判断,所以这里只返回了1和-1#include#includedouble 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<="">qsort(s,n,sizeof(s[0]),cmp);for(i=0;ireturn(0);}No.4.对一个字符数组排序.原理同int#include#include#includechar s[10000],i,n;int cmp(const void *a,const void *b){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#includestruct 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++)< p="">{s[i].no=i+1;scanf("%lf",&s[i].date1);}qsort(s,n,sizeof(s[0]),cmp);for(i=0;ireturn(0);}No.6.对结构体排序.加入no来使其稳定(即data值相等的情况下按原来的顺序排)#include#includestruct 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);elsereturn((aa->no)-(bb->no));}int main(){scanf("%d",&n);for(i=0;i<n;i++)< p="">{s[i].no=i+1;scanf("%lf",&s[i].date1);}qsort(s,n,sizeof(s[0]),cmp);for(i=0;ireturn(0);}No.7.对字符串数组的排序(char s[][]型) #include#include#includechar 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<="">qsort(s,n,sizeof(s[0]),cmp);for(i=0;i<="">return(0);}No.8.对字符串数组排序(char *s[]型) #include#include#includechar *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++)< p="">{s[i]=(char*)malloc(sizeof(char*));scanf("%s",s[i]);}qsort(s,n,sizeof(s[0]),cmp);for(i=0;i<="">return(0);}9、计算几何中求凸包的cmpint cmp(const void *a, const void *b){TPoint *c = (TPoint *)a;TPoint *d = (TPoint *)b;double k = multi(*c, *d, point[0]); //p0c×p0d (若>0 说明c的极角小于d, 若<0, c的极角大于d)if( k< 0) return 1; // 若前面的大于后面的,返回1--- 表示升序(交换)else if(k == 0 && distance(*c, point[0]) >= distance(*d, point[0])) return 1; // 把距离远的丢在后面,这么做扫描时才可以删掉近的else return -1; }</n;i++)<> </n;i++)<> </n;i++)<>。
c语言排序函数
C语言排序函数可以分为两大类:比较排序与非比较排序。
比较排序:
·冒泡排序(Bubble Sort):通过比较两个相邻的元素来排序,每
次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系的要求,如果不满足就让它俩互换。
·快速排序(Quick Sort):通过一趟排序将要排序的数据分割成独
立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,
然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递
归进行,以此达到整个数据变成有序序列。
·选择排序(Selection Sort):首先在未排序的数据中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中
继续寻找最小(大)元素,然后放到已排序序列的末尾。
以此类推,直到
所有元素均排序完毕。
·插入排序(Insertion Sort):将未排序数据插入到已排序序列中,位置不对就反复比较与交换,直到找到合适的位置,一次插入一个排序元素,直到所有元素都插入到正确位置。
·希尔排序(Shell Sort):先将整个待排序的记录序列分割成为若
干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,
再对全体记录进行依次直接插入排序。
C语言快速排序算法用快速排序法对一组数据由小到大进行排序,数据分别为99、45、12、36、69、22、62、796、4、696。
实现过程:(1)自定义一个函数qusort(),实现快速排序。
(2) main() 函数为程序的入口函数。
程序代码如下:1.#include<stdio.h>2.int qusort(int s[],int start,int end)//自定义函数 qusort()3.{4.int i,j;//定义变量为基本整型5. i=start;//将每组首个元素赋给i6. j = end;//将每组末尾元素赋给j7. s[0]=s[start];//设置基准值8.while(i<j)9.{10.while(i<j&&s[0]<s[j])11. j--;//位置左移12.if(i<j)13.{14. s[i]=s[j];//将s[j]放到s[i]的位置上15. i++;//位置右移16.}17.while(i<j&&s[i]<=s[0])18. i++;//位置左移19.if(i<j)20.{21. s[j]=s[i];//将大于基准值的s[j]放到s[i]位置22. j--;//位置左移23.}24.}25. s[i]=s[0];//将基准值放入指定位置26.if(start<i)27.qusort(s,start,j-1);//对分割出的部分递归调用qusort()函数28.if(i<end)29.qusort(s,j+1,end);30.return0;31.}32.33.int main()34.{35.int a[11], i;//定义数组及变量为基本整型36.printf("请输入10个数:\n");37.for(i=1;i<=10;i++)38.scanf("%d",&a[i]);//从键盘中输入10个要进行排序的数39.qusort(a,1,10);//调用qusort()函数进行排序40.printf("排序后的顺序是:\n");41.for(i=1;i<=10;i++)42.printf("%5d",a[i]);//输出排好序的数组43.printf("\n");44.return0;45.}运行结果:。
C语⾔之——快速排序(图解)C语⾔之--快速排序纯属学习记录,仅供参考。
快速排序快速排序:(1)⾸先规定⼀个“基准”,将数据分为两个部分。
(2)将⼤于等于(⼤于)的数据放在基准的右⾯,将⼩于(⼩于等于)的数据放在基准的左⾯。
(3)然后,左⾯的数据⼜可以规定⼀个基准,分为两部分;右⾯的数据也可以规定⼀个基准,也分为两部分。
递归下去。
(4)直到分到不可再分,或数据有序。
如果右⾯找到⼀个⼩于基准的数,左⾯找到⼀个⼩于基准的数,⽽且左右没有相遇则交换左右数据。
如果左右相遇了,那么就把基准与相遇点数据交换。
⾃此,将序列分为左右两部分。
左⾯的⼩于基准,右⾯的⼤于基准。
代码⽰例:#include <stdio.h>#include <string.h>void QuickSort(char arry[], int L, int R);void main(void){int i;char arry[8] = {5, 4, 9, 8, 7, 6, 2, 1};printf("原来顺序:\n");for (i = 0; i < sizeof (arry); i++){printf("%d\t", arry[i]);}printf("\n");QuickSort(arry, 0, 7);printf("排序后:\n");for (i = 0; i < sizeof (arry); i++){printf("%d\t", arry[i]);}printf("\n");return;}void QuickSort(char arry[], int L, int R){int left = L,right = R;int x;int Centor = 0,temp = 0;if (L > R){return;}Centor = arry[L];//基准保存在Centor中while (left != right)//left 与 right 没有相遇则继续循环交换{while (arry[right] >= Centor && left < right)//如果右⾯的数⼤于基准跳过,⼩于基准停⽌,{right--;}while (arry[left] <= Centor && left < right)//如果左⾯的数⼩于基准跳过,⼤于基准停⽌,{left++;}if (left < right)//如果left 与 right 没有相遇,则将右⾯⼩于基准的数与左⾯⼤于基准的数交换 {temp = arry[left];arry[left] = arry[right];arry[right] = temp;}//显⽰交换后的序列for (x = 0; x < 8; x++){printf("%d\t", arry[x]);}printf("\n");}//如果left 与 right 相遇则将基准以相遇的位置数据互换,⾄此就将数据分为了左右两部分//左⾯的⼩于基准,右⾯的⼤于基准arry[L] = arry[left];arry[left] = Centor;//将左⾯的继续进⾏排序QuickSort(arry, L, left-1);//将右⾯的继续进⾏排序QuickSort(arry, right+1, R);}输出结果:原来顺序:5498762154187629541276895412768921457689214576891245768912456789排序后:12456789。