排序问题 三

来源:互联网 发布:qt5 udp socket编程 编辑:程序博客网 时间:2024/05/22 17:36

前面我们已经稍微的提到了快排,在这里会较详细的说一下快排,嘿嘿,或许不是很专业,话不多说。Let’s go!

还是问一下,什么叫做快排?

快速排序的基本思想是,通过一轮的排序将序列分割成独立的两部分,其中一部分序列的关键字(这里主要用值来表示)均比另一部分关键字小。继续对长度较短的序列进行同样的分割,最后到达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故减少了比较次数,缩短了排序时间,其实快排是由冒泡演变的。

  详细描述:首先在要排序的序列 a 中选取一个中轴值(基准值),而后将序列分成两个部分,其中左边的部分 b 中的元素均小于或者等于 中轴值,右边的部分 c 的元素 均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。

  “基准值”的选择有很多种方法。最简单的是使用第一个记录的关键字值。但是如果输入的数组是正序或者逆序的,就会将所有的记录分到“基准值”的一边。较好的方法是随机选取“基准值”,这样可以减少原始输入对排序造成的影响。但是随机选取“基准值”的开销大。

  为了实现一次划分,我们可以从数组(假定数据是存在数组中)的两端移动下标,必要时交换记录,直到数组两端的下标相遇为止。为此,我们附设两个指针(下角标)i 和 j, 通过 j 从当前序列的有段向左扫描,越过不小于基准值的记录。当遇到小于基准值的记录时,扫描停止。通过 i 从当前序列的左端向右扫描,越过小于基准值的记录。当遇到不小于基准值的记录时,扫描停止。交换两个方向扫描停止的记录 a[j] 与 a[i]。 然后,继续扫描,直至 i 与 j 相遇为止。扫描和交换的过程结束。这是 i 左边的记录的关键字值都小于基准值,右边的记录的关键字值都不小于基准值。

  通过两个不相邻元素交换,可以一次交换消除多个逆序,加快排序速度。快速排序方法在要排序的数据已经有序的情况下最不利于发挥其长处。

以上是一种思路,它的缺点是不稳定,对于相等的在排序和找“基准值”的时候就可能有错误。下面来重点讲一下另外一种(个人觉得这种比较简单)

——————————————————————————————————————-

先介绍几个知识点:

1.我们在调用的时候用到sqrt()
功 能: 使用快速排序例程进行排序
头文件:stdlib.h
用 法:包括4部分 void qsort(void base,int nelem,int width,int (*fcmp)(const void ,const void *));
参数: 1 待排序数组首地址
2 数组中待排序元素数量
3 各元素的占用空间大小(一般是数组的第一个如a[0])
4 指向函数的指针,用于确定排序的顺序
2.要用到compare(),我们通常简写是cmp()
cmp()是一个比较函数(写成cmp是个人喜好,也可以写成qcmp什么的),典型的cmp的定义是int cmp(const void x, const void *y),返回值是int,两个参数类型必须是const void,这里的x, y是我随便定义的,cmp()函数是这样的,假如是升序,就是x>y,返回值>0; 小于的话,返回值<0;相等的话,返回值=0.

qsort()的基本模板

#include<stdio.h>#include<stdlib.h>int cmp(const void *x, const void *y)//这是对元素的升序快排,如果要降序的话就把1与-1换一下 {    if(*(元素类型 *)x>*(元素类型 *)y)//根据元素的值进行排序     {        return 1;    }    else if(*(元素类型 *)x==*(元素类型 *)y)    {        return 0;    }    else     {        return -1;    }}int main(){    元素类型a[W];//W是数组的大小    qsort(a, cnt, sizeof(a[0], cmp));//对数组a[]排序,cnt是要排序的元素的个数,cmp是调用函数     return 0;}

下面我们举个例子吧

题意就是给先给你一个n,后面接着有n组数据,升序排序。

#include<stdlib.h>int cmp(const void *x, const void *y){    if(*(int *)x>*(int *)y)    {        return 1;    }    else    {        return -1;    }}int main(){    int n, i, a[100], temp;    while(~scanf("%d", &n))    {        for(i=0;i<n;i++)        {            scanf("%d", &a[i]);        }        qsort(a, n, sizeof(a[0]), cmp);        for(i=0;i<n;i++)        {            printf("%d ", a[i]);        }        printf("\n");    }    return 0;}

补充:

快排针对的是int、char、double、float形式的数组的快排。
———————————————————————————————————————————————————拓展一下:

一.对结构体某元素的快排

1.一级结构体排序

#include<stdio.h>#include<stdlib.h>int cmp(const void *p, const void *q);//声明函数struct ln{    int data;    int score;    int math;}ss[V];//V为数组大小int main(){    qsort(ss, cnt sizeof(struct ln), cmp);//对结构体ss进行快排//cnt为要排的元素的个数}int cmp(const void *p,const void *q)//该函数进行的是升序快排,如果想要进行降序快排,则将1和-1调换即可{     return (*(struct ln*)p).data>(*(struct ln*)q).data?1:-1;//根据结构体中data的值进行排序}

2.二级结构体排序

int cmp(const void *p,const void *q)//该函数进行的是升序快排,如果想要进行降序快排,则将1和-1调换即可{    if((*(struct ln*)p).data==(*(struct ln*)q).data)//结构体中data的值相等    {         return (*(struct ln*)p).score>(*(struct ln*)q).score?1:-1;//根据结构体中score的值进行排序    }     else    {         return (*(struct ln*)p).data>(*(struct ln*)q).data?1:-1;//根据结构体中data的值进行排序    } }

3.多级类推

二.对结构体重字符串的快排

#include<stdio.h>#include<string.h>#include<stdlib.h>struct ln{    int data;    char ch[v];//v为数组大小}ss[V];//V为数组大小int cmp(const void *p,const void *q){    return strcmp((*(struct ln*)p).ch,(*(struct ln*)q).ch );}int main(){    qsort(ss,cnt,sizeof(ss[0]),cmp);//对结构体ss按照结构体中字符串ch的字典顺序进行快排//cnt为要排的元素的个数}
0 0
原创粉丝点击