搜索初步–冒泡排序加二分法与选择排序加二分法
介绍:线性搜索的方法即将数组从头到尾遍历以找到目标,但如果数据量过于庞大且目标在其中为随机存在,则会使搜索效率大大降低,因此我们可以用更加高效的方法解决该问题,即二分法搜索。
本文思路:
1.二分法
2.冒泡排序法与选择排序法。
3.冒泡排序加二分法与选择排序加二分法。
(为标题而来直接往下拉)
4.这两种搜索方法的缺点与优点。
##二分法
大前提:是一组从小到大的数组,类比于平面直角坐标系中的X轴,只有在有序的序列中进行二分才有意义。
思路:先取最左边的数组角标(left)与最右边的数组角标(right)以确定我们寻找的段落大小并求出中间数的角标(mid0,注意区分数组的角标与数组的值是不一样的,然后通过判断数组中间值与目标值的大小来调整我们的段落大小。如果目标值比中间值大,则段落的左端向右移动使其成为(mid+1),并重新计算mid的角标以确定mid的值;
如果目标值比中间值小,则段落的右端向左端移动使其成为(mid-1),并重新计算mid的角标以确定mid的值。
依次类推,直到left与right的值相同,此时已经将该数组遍历完全。
代码
#include<stdio.h>
int main()
{
int x,i,left,right,mid,flag,goal,str[100];
//x是数组的实际元素个数,goal为目标,flag为一个判断有无找到的开关。
scanf("%d",&x);
for(i=0;i<x;i++)
scanf("%d",&str[i]);
left=0;right=x-1;mid=(left+right)/2;flag=0;
while(left!=right)
{
if(str[mid]<goal)
{
left=mid+1;
mid=(left+right)/2;
}
if(str[mid]>goal)
{
right=mid-1;
mid=(left+right)/2;
}
if(str[mid]==goal)
{
flag=1;
printf("%d",goal)//找到目标。
break;
}
}
if(flag==0)
return -1;//没有找到目标。
return 0;
}
##冒泡排序与选择排序
介绍:受限制于二分法的大前提,如果所给的数据是无序的则无法使用二分法,为达到使用二分法的目的(毕竟别的方法我现在也不会用),所以我们将无序变为有序,所以引入冒泡排序加二分法与选择排序加二分法。
####冒泡排序:实际是两两交换以达到排序目的的过程,平均时间复杂度与元素个数的关系为n的平方。
###选择排序:实际是排队打擂然后交换而队伍长度越打越短以达到排序目的的过程,时间复杂度与元素个数的关系介于0到n之间。
(从这里已经可以看出选择排序优于冒泡排序,但是我们学校老师在教学时重点强调了冒泡排序,而非选择排序,可能下学期学了能解答这个问题。)
代码
冒泡排序
#include<stdio.h>
int main()
{
int x,i,j,tmp,str[100];
//x为实际存入数组的个数,tmp是在做交换时的中间值。
scanf("%d",&x);
for(i=0;i<x;i++)
scanf("%d",&str[i]);
for(i=0;i<x;i++)
{
for(j=0;j<x-i-1;j++)
{
if(str[j]>str[j+1])
{
tmp=str[j];
str[j]=str[j+1];
str[j+1]=tmp;
}
}
}
for(i=0;i<x;i++)
printf("%d ",str[i]);
return 0;
}
选择排序
#include<stdio.h>
int main()
{
int x,i,maxid,ma,j,tmp,str[100];
//x为未知数个数,maxid记录最大值角标,tmp作为交换数值的容器。
maxid=0;
scanf("%d",&x);
for(i=0;i<x;i++)
scanf("%d",&str[i]);
for(i=x-1;i>1;i--)
{
ma=-1;//不要忘记在每次的遍历中初始化最大值。
for(j=0;j<=i;j++)
{
if(str[j]>ma)
{
ma=str[j];
maxid=j;
}
}
tmp=str[i];
str[i]=str[maxid];
str[maxid]=tmp;
}
for(i=0;i<x;i++)
printf("%d ",str[i]);
return 0;
}
##冒泡排序加二分法与选择排序加二分法
代码:
冒泡排序加二分法
#include<stdio.h>
void bouble(int str[],int x)
{
int i,j,tmp;
for(i=0;i<x;i++)
{
for(j=0;j<x-i-1;j++)
{
if(str[j]>str[j+1])
{
tmp=str[j];
str[j]=str[j+1];
str[j+1]=tmp;
}
}
}
}
int dichotomy(int str[],int x,int goal)
{
int left,right,mid,flag;
left=0;right=x-1;mid=(left+right)/2;flag=0;
while(left!=right)
{
if(str[mid]<goal)
{
left=mid+1;
mid=(left+right)/2;
}
if(str[mid]>goal)
{
right=mid-1;
mid=(left+right)/2;
}
if(str[mid]==goal)
{
flag=1;
return 1;
break;
}
}
if(flag==0)
return -1;
}
int main()
{
int str[100],goal,x,i;
scanf("%d %d",&x,&goal);
for(i=0;i<x;i++)
scanf("%d",&str[i]);
bouble(str,x);
printf("%d",dichotomy(str,x,goal));
return 0;
}
选择排序加二分法
#include<stdio.h>
int dichotomy(int str[],int x,int goal)
{
int left,right,mid,flag;
left=0;right=x-1;mid=(left+right)/2;flag=0;
while(left!=right)
{
if(str[mid]<goal)
{
left=mid+1;
mid=(left+right)/2;
}
if(str[mid]>goal)
{
right=mid-1;
mid=(left+right)/2;
}
if(str[mid]==goal)
{
flag=1;
return 1;
break;
}
}
if(flag==0)
return -1;
}
void choice(int str[],int x)
{
int i,maxid,maxx,j,tmp;
maxid=0;
for(i=x-1;i>1;i--)
{
maxx=-1;
for(j=0;j<=i;j++)
{
if(str[j]>maxx)
{
maxx=str[j];
maxid=j;
}
}
tmp=str[i];
str[i]=str[maxid];
str[maxid]=tmp;
}
}
int main()
{
int str[100],goal,i,x;
scanf("%d %d",&x,&goal);
for(i=0;i<x;i++)
scanf("%d",&str[i]);
choice(str,x);
printf("%d",dichotomy(str,x,goal));
return 0;
}
##两种方法的优点与缺点
优点:我们至少掌握了一种搜索方法。
缺点:它只能告诉你有没有,而不能告诉你它在哪里。