二分查找的递归与非递归程序,跟踪分析执行时间,分析两种算法的复杂性。
二分查找算法思想:
二分又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。
快速排序算法思想:
定义变量low、high分别标识数组的第一个元素下标和最后一个元素下标,变量key先存储第一个数组arr[0],以后key的值都为划分后的第一个元素,先从数组的后面看起,high–直到发现有一个数小于key,arr[low]=arr[high],因为此时已经确定arr[low]比key小,所以low++,直到low=high;利用递归来实现对已经划分的数组再次划分,直到划分的左右两边都只有一个数。
我以前的博客有写过快排的Java实现代码,想学习的同学可以参考。
递归和非递归思想:
将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。通过一次比较,将查找区间缩小一半。
算法步骤描述:① 首先确定整个查找区间的中间位置 mid = ( left + right ) / 2; ② 用待查关键字值与中间位置的关键字值进行比较,只要相等,就查找成功 如果大于,则在后(右)半个区域继续进行折半查找 如果小于,则在前(左)半个区域继续进行折半查找 ③ 对确定的缩小区域再按折半公式,重复上述步骤。 最后,得到结果:要么查找成功, 要么查找失败。 流程图如下: 递归流程图 非递归流程图 |
算法代码调试过程及输入输出结果:
例如输入数组大小为500时:
对实验数据进行图表分析:(Excels和ppt生成)
源代码附上:
#include <bits/stdc++.h>//C++万能库
//排序算法设计(快速排序)
void QuickSort(int *arr,int low,int high){
if(low<high){
int i=low;
int j=high;
int key=arr[low];
while(i<j){
while(i<j&&arr[j]>=key) j--;
if(i<j)
arr[i++]=arr[j];//先赋值在自增
while(i<j&&arr[i]<key) i++;
if(i<j)
arr[j--]=arr[i];//先赋值再自增
}
arr[i]=key;
QuickSort(arr,low,i-1);//左边排序
QuickSort(arr,i+1,high);//右边排序
}
}
//二分查找递归算法设计
int recursion_BinarySearch(int *a, const int& x, int left, int right){
int middle = (left + right) / 2;
if (x == a[middle]){
return middle;//查找成功,直接返回下标
}
if (left >= right){
return 0;
} else if (x > a[middle]){
return recursion_BinarySearch(a, x, middle + 1, right);//x>a[n/2]时,只要在数组a的右半部继续搜索x
} else if (x < a[middle]){
return recursion_BinarySearch(a, x, left, middle - 1);//如果x<a[n/2],则我们只要在数组a的左半部继续搜索x
}
return 0;
}
//二分查找非递归算法设计
int not_recursion_BinarySearch(int *a, const int &x, int n){
int left = 0;
int right = n - 1;
while (left <= right){
int middle = (left + right) / 2;
if (x == a[middle]){
return middle;//查找成功,返回下标
} else if (x > a[middle]){
left = middle + 1;//x>a[n/2]时,只要在数组a的右半部分继续搜索x
} else{
right = middle - 1;//如果x<a[n/2],则我们只要在数组a的左半部继续搜索x
}
}
return 0;
}
int main(){
int n;
printf("请输入随机有序数组的大小n(1~n):");
scanf("%d",&n);
putchar('\n');//换行
int *arr = new int[n];
time_t time_;//生成时间种子
srand((unsigned)time(&time_));//随机数发生器的初始化
int i=0;
while(i < n){
arr[i] = rand() % 10000 + 1;//生成随机数
++i;
}
//快速排序
QuickSort(arr,0,n);
//输出框的格式设置(一行十个数)
printf("自动生成的随机有序数组如下:\n");
for (int i = 0; i < n; i++){
if (i % 30== 0){
putchar('\n');
} else{
printf("%d ",*(arr+i));
}
}
putchar('\n');
int x;
for (int i = 0; i < 10; i++){
printf("请输入需查找数值:");
scanf("%d",&x);
clock_t start1, end1, start2, end2;
int recursion_loc, not_recursion_loc;
//计算递归二分查找时间
start1 = clock();
for (int i = 0; i < 10000000; i++)//一次搜索速度太快,所以循环多次
{
recursion_loc = recursion_BinarySearch(arr, x, 0, n - 1);
}
end1 = clock();
//计算非递归二分查找时间
start2 = clock();
for (int i = 0; i < 10000000; i++)
{
not_recursion_loc = not_recursion_BinarySearch(arr, x, n);
}
end2 = clock();
double time1 = ((double)(end1 - start1) / 1000);
double time2 = ((double)(end2 - start2) / 1000);
if (recursion_loc == 0) puts("递归方法未找到");
else{
printf("递归方法: ");
printf("%d",x);
printf(" 的位置是第 ");
printf("%d",recursion_loc);
printf(" 位 所用时间: ");
printf("%.5lf",time1);
puts("s");
}
if (not_recursion_loc == 0) puts("非递归方法未找到");
else{
printf("非递归方法: ");
printf("%d",x);
printf(" 的位置是第 ");
printf("%d",not_recursion_loc);
printf(" 位 所用时间: ");
printf("%.5lf",time2);
puts("s");
}
}
return 0;
}