您的位置:首页 > 其它

--1 排序与查找 基础算法

2017-07-17 18:31 316 查看
  对于排序,常规而言,有几种可以手动实现的排序方式。

  一是选择排序,将a[1]......a
的序列进行排序,其实现代码见下:

void select_sort(int *a)
{
for(int i=1;i<n;i++) //进行 n-1 轮选择
for(int j=i+1;j<=n;j++) //第 i 轮选择是选择第 i 大元素排在 A[i]。
if(a[i]<a[j]) swap(a[i],a[j]);
}
第二种较常听说的即为冒泡排序,其思路大致就像泡泡上冒,将最 大/小 的 元素值 向前冒。

代码附下:

void bubble_sort(int *a)
{
for(int i=1;i<n;i++) //进行 n-1 轮冒泡
for(int j=1;j<=n-i;j++) //第 i 轮冒泡把第 i 大排在 a[n-i+1]的
if(a[j]>a[j+1]) swap(a[j],a[j+1]);
}


对数列每个元素的值较小的情况下,也有计数排序(是这么叫哈?)一途,

即输入时统计元素值出现次数,再循环输出即可

void sort()
{
int a[maxn],maxv=0;  // maxv统计元素值最大值;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
a[x]++;   // 统计x出现次数;
maxv=max(maxv,x);
}
for(int i=1;i<=maxv;i++)
{
if(a[i]) printf("%d\n",i);
}
}


当然如果元素值可能为负,可以进行数组平移,即定义a[i+maxn]=a[i].

当然,上述几种算法并不在算法竞赛中经常投入使用,因为它们的时间复杂度O(n2)实在令人难以接受。

------------------------------------------------------------------------------
就便利而言,STL模板中的sort函数显得更加常用。
引用<algorithm> 库后 ,可以使用sort()函数;
对sort的调用就又有几种情况了

一、缺省定义
对a[1]....a
排序; 有如下几种方式 sort(a+1,a+n+1);
sort(&a[1],&a[n+1]);


在缺省定义下,sort函数有两个参数需要输入;

第一个参数的意义为首元素的地址

第二个参数的意义为末元素的后一个元素的地址。 

缺省定义下sort默认进行从小到大排序;

二、自定义比较函数

bool mycmp(int a,int b) //如果 a 排在 b 的前面,则返回 true
{
return a>b; //如果 a>b 则 a 排在 b 的前面
}


如所示代码,

调用方式:

sort(a+1,a+n+1,mycmp);

将进行你自定义的比较行为,

三、如果排序对象是结构体

那么同样需要用到自定义比较函数或者是在结构体内进行符号重定义

e.g.:

如一次考试成绩,有语文,英语,数学三科成绩和学号属性,要求进行多关键字排序

总分高的排前面,

总分相同的数学成绩高的排前面,

数学成绩相同的语文成绩高的排前面,

语文成绩相同的学号小的排前面,

定义结构体:

struct stu
{
int id
4000
,math,chi,eng,all;
};


all自然等于 math+chi+eng

定义自定义比较函数

bool cmp(stu a,stu b)
{
if(a.all!=b.all) return a.all<b.all; // 总成绩靠前
if(a.math!=b.math) return a>b //数学靠前
if(a.chi!=b.chi) return a.chi>b.chi;
if(a.eng!=b.eng) return a.eng<b.eng;
return a.id<b.id;
}


如上,如果满足条件直接跳出,

否则进行下一次判断

或者对结构体进行符号重定义

嗯,如上

struct stu
{
int id,math,chi,eng,all;
bool friend bool operator < (stu a,stu b)
{
if(a.all!=b.all) return a.all<b.all; // 总成绩靠前
if(a.math!=b.math) return a>b //数学靠前
if(a.chi!=b.chi) return a.chi>b.chi;
if(a.eng!=b.eng) return a.eng<b.eng;
return a.id<b.id;
}};


可以观察两种方式非常相似,选择哪一种方式还是看自己习惯吧,我觉得。

---------------------------------------------------------------------------------

STL库中还提供了几种便利的二分查找函数。

upper_bound(),lower_bound(),binary_search();

当然这几个函数用二分为基础优化算法是建立在已排好序的队列(且应为递增序列)当中运行的,

如果是乱序数组,将会得出错误结果。

下面对三种函数进行功能的简述

1、upper_bound()   寻找数列中第一个大于某一值的元素的位置

2、lower_bound()   寻找数列中第一个大于等于某一值的元素的位置

3、binary_search()  在序列查找某一值是否存在,如果存在  则返回 true,否则返回 false

三种函数的调用

bool p=binary_search(A+1,A+n+1,v);  //存在性判断

int p=lower_bound(A+1,A+n+1,v)-A;   //元素下标  若不存在为 n+1

int p=upper_bound(A+1,A+n+1,v)-A;  // 元素下标  若不存在为 n+1

顺便一提,分治算法也可以实现快速排序,复杂度为O(nlog2n)

思想为二分序列,整理左侧序列,整理右侧序列,进行二路归并,实现整个序列有序;

代码附上:

void devide(int *a ,int x,int y)
{
if(y-x==1) return;

int m=(x+y)/2;

devide(a,x,m);
devide(a,m,y);

int i=x,j=m,k=x;

while(i<m&&j<y)
{
if(a[i]>a[j]) t[k++]=a[j++];
else t[k++]=a[i++];
}
while(i<m) t[k++]=a[i++];
while(j<y) t[k++]=a[j++];

for(int p=x;p<y;p++)
{
a[p]=t[p];
}

}











                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: