对于查找一个数组中某个元素的方法最基本、最简单的查找是顺序查找,对于已经排好序的数组,可以采用二分查找。二分比顺序查找更高效。
1.查找
1.1 顺序查找
从数组的第一个元素开始,依次往后比较,直达找到满足条件的那个位置的元素,输出元素位置或该位置上元素的值。
int array[7]={2,3,4,6,7,9,10};
int x;
cout<<"请输入要查找的数据";
cin>>x;
for(k=0;k<7;++k)
{
if(x==array[k]) break;
if(k==7)
cout<<"没有找到";
}
1. 2 二分查找
当被查找的数组很大,要查找的元素又靠近数组的尾端,或在数组中根本不存在,则查找的时间就可能会很长。
二分查找的思想是:(先将待查数组排序好)
(1)首先在整个表中查找中间元素;
(2)根据这个元素的值确定下一步将在哪半边进行查找,将查找范围缩小一半,继续用同样的方法查找。
注:要实现这种查找方法,需要记录两个下标值,分别表示要被搜索范围的两个端点的下标值。这两个值分别存储于变量low和high中,表示左边界和右边界。开始时,搜索范围覆盖整个数组,而随着查找的继续进行,搜索区间将逐渐缩小,直到元素被找到。如果最后两个下标值交叉了,那么表示所要查找的值不在数组中。
//二分查找
#include<iostream>
using namespace std;
int main()
{
int low,high,,mid,x;
int array[]={0,1,2,3,4,5,6,7,8,9};
cout<<"请输入要查找的数据"; cin>>x;
low=0;high=9;
while(low<high) //只要查找区间存在,基于哨兵的循环
{
mid=(low+high)/2; //计算中间位置
if(x==array[mid]) break; //找到了
if(x<array[mid])
{
high=mid-1;
} //修改查找区间
else
{
low=mid+1;
}
if(low>high)
cout<<"没有找到"<<endl;
else
cout<<x<<"的位置是:"<<mid<<endl;
}
return 0
}
1.3 顺序查找vs二分查找
对于n个数据元素的数组,假如都是最坏结果–都要查找到最后一步,顺序查找法要查找n次,而二分查找只需要查找log2(n)次。
n | 10 | 100 | 1000 | 1 000 000 | 1 000 000 000 |
---|---|---|---|---|---|
log2(n) | 3 | 7 | 10 | 20 | 30 |
2.排序
上边提到使用二分查找之前,需要先将数组按次序排序。常用的排序方法很多,如插入排序、选择排序、交换排序
2.1 直接选择排序法
(1)在所有元素中找到最小的元素放在数组的第0个位置;
(2)在剩余元素中找到最小的元素放在素组的第1个位置,以此类推,知道所有元素都放在适当的位置。
注:找出第一个元素要比较n次,找出第二个元素比较n-1次,…,找出第n个元素比较一次。因此,总的比较次数为:
1 + 2 + 3 + … + n = n ( n + 1 ) / 2则称时间复杂性为O(n2)
//直接选择排序
#include <iostream>
using namespace std;
int main( )
{
int lh, rh, k, tmp;
int array[ ] = {2, 5, 1, 9, 10, 0, 4, 8, 7, 6};
for (lh = 0; lh < 10; ++lh) { // 依次将正确的元素放入array[lh]
rh = lh;
for (k = lh; k < 10; ++k) // 找出从lh到最后一个元素中的最小元素的下标rh
if ( array[k] < array[rh] ) rh = k;
tmp = array[lh]; //交换lh和rh的值
array[lh] = array[rh];
array[rh] = tmp;
}
for (lh =0; lh<10; ++lh) cout << array[lh] << ' ';
return 0;
}
2.2冒泡排序
冒泡排序适合原先数据就是比较有序的数组元素。
总结如下:排序n个元素,需要进行n-1次起泡,这个n-1次起泡过程可以用一个1到n-1的for循环来控制。第i次起泡的结果是将第i大的元素交换到第n-i号单元,而第n-i单元在数组中存放在第n-i-1位置中。第i次起泡就是检查下标0到n-i-1的元素,如果这个元素和它后边的元素违反了排序要求,则交换这两个元素。这个过程可以用一个从0到n-i-1的for循环来实现。所以整个冒泡排序就是一个两层嵌套的for循环。
#include <iostream>
using namespace std;
int main()
{
int a[11] = { 0, 3, 5, 1, 8, 7, 9, 4, 2, 10, 6};//11个元素需要10次冒泡
int i, j, tmp;
bool flag; //记录一趟起泡中有没有发生过交换
int n=11;
for (i=0; i<n-1; i++) { // 控制10次起泡,n-1次起泡过程,每次冒泡能挑选出一个次最大值
flag = false;
for (j=0; j<n-1-i; j++) // 一次起泡过程,每次冒泡要比较n-i-1个相邻元素
if (a[j+1] < a[j])
{tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; flag = true;}
if (!flag) break; //一趟起泡中没有发生交换,排序提前结束
}
cout << endl;
for (i=0; i<n; ++i) cout << a[i] << ' ';
return 0;
}