练习1-1 二分查找
分数 20
作者 陈越
单位 浙江大学
查找算法中的“二分法”是这样定义的:给定 n 个从小到大排好序的整数序列 data,以及某待查找整数 x,我们的目标是找到 x 在 data 中的位置。
具体来说,不妨假设整数序列存储为一个序列 array,这个序列的结构定义在下面给出,数据存放在数组 data 中。若有 array->data[i] = x,则返回 i;否则返回失败标记 NotFound 表示没有找到。注意 C 语言数组下标从 0 开始。
二分法是先找到序列的中点 array->data[middle],与 x 进行比较,若 array->data[middle] > x,则在左边的子序列中查找 x;若 array->data[middle] < x,则在右边的子序列中查找 x; 否则两者相等,则返回中点下标 middle。试用一个函数实现二分查找的功能,并分析最坏、最好情况下的时间、空间复杂度。
函数接口定义:
Position BinarySearch ( ArrPtr array, ElemSet x ) ;
其中ArrPtr结构定义如下:
typedef int Position; typedef struct ArrNode *ArrPtr;struct ArrNode { ElemSet *data; int size; };
函数接口定义中,ElemSet 是用户定义的数据类型,例如 int、double 或者 char 等,要求可以通过 >、==、< 进行比较,并且题目保证传入的数据是递增有序 的。
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> #define kMaxSize 10 #define NotFound -1 typedef int ElemSet;typedef int Position; typedef struct ArrNode *ArrPtr;struct ArrNode { ElemSet *data; int size; }; Position BinarySearch ( ArrPtr array, ElemSet x ) ;int main (void ) { int i, n; ArrPtr array; ElemSet x; array = (ArrPtr)malloc (sizeof (struct ArrNode)); scanf ("%d" , &n); array->size = n; array->data = (int *)malloc (sizeof (int )*array->size); for (i=0 ; i<n; i++) { scanf ("%d" , &array->data[i]); } scanf ("%d" , &x); printf ("%d\n" , BinarySearch (array, x)); return 0 ; }
输入样例 1:
输出样例 1:
输入样例 2:
输出样例 2:
解答
Position BinarySearch ( ArrPtr array , ElemSet x ) { int left = 0 ; int right = array ->size - 1 ; int middle; while (left <= right) { middle = (left + right) / 2 ; if (array ->data[middle] == x) { return middle; } else if (array ->data[middle] < x) { left = middle + 1 ; } else { right = middle - 1 ; } } return NotFound; }
注意
1.middle 要在循环内部赋值,每次循环middle都要变。
2.left 和 right都要跟middle有关,不是left += (left+right)/ 2 ,left 为 middle 加一, right 为 middle 减一。
实验1-1 有序数组的插入
实验1-1 有序数组的插入
分数 20
作者 陈越
单位 浙江大学
给定存储了 n 个从大到小排好序的整数,试将任一给定整数 x 插入数组中合适的位置,以保持结果依然有序。分析算法在最坏、最好情况下的时间、空间复杂度。
具体来说,不妨假设整数序列存储为一个序列 array,这个序列的结构定义在下面给出,数据存放在数组 data 中。因为数组长度是有限的,我们在此假设 data 数组的最大长度为 kMaxSize。如果在执行插入之前,数组已经满了,则插入失败,返回 false;如果待插入的元素 x 已经在 data 中,则不要重复插入,返回 false;如果插入成功,则返回 true。
函数接口定义:
bool DecrSeqInsert ( ArrPtr array, ElemSet x ) ;
其中ArrPtr结构定义如下:
typedef int Position; typedef struct ArrNode *ArrPtr;struct ArrNode { ElemSet *data; int size; };
函数接口定义中,ElemSet 是用户定义的数据类型,例如 int、double 或者 char 等,要求可以通过 >、==、< 进行比较。这里题目保证传入的数据是递减 有序的。
裁判测试程序样例:
#include <stdio.h> #include <stdlib.h> #define kMaxSize 100 typedef enum { false , true } bool ;typedef int ElemSet;typedef int Position; typedef struct ArrNode *ArrPtr;struct ArrNode { ElemSet *data; int size; }; bool DecrSeqInsert ( ArrPtr array, ElemSet x ) ;int main (void ) { int i, n; ArrPtr array; ElemSet x; array = (ArrPtr)malloc (sizeof (struct ArrNode)); scanf ("%d" , &n); array->size = n; array->data = (int *)malloc (sizeof (int ) * kMaxSize); for (i=0 ; i<n; i++) { scanf ("%d" , &array->data[i]); } scanf ("%d" , &x); if (DecrSeqInsert (array, x) == false ) { printf ("Insertion failed.\n" ); } printf ("%d" , array->data[0 ]); for (i=1 ; i<array->size; i++) { printf (" %d" , array->data[i]); } printf ("\n" ); printf ("Array size = %d\n" , array->size); return 0 ; }
输入样例 1:
输出样例 1:
35 12 10 8 7 3 Array size = 6
输入样例 2:
输出样例 2:
Insertion failed. 35 12 10 8 7 3 Array size = 6
解答
bool DecrSeqInsert ( ArrPtr array , ElemSet x ) { if (array ->size >= kMaxSize) { return false ; } int i , j , k; for (i = 0 ; i <array ->size; i++) { if (x == array ->data[i]) { return false ; } } for (j = 0 ; j < array ->size; j++) { if (x > array ->data[j]) { break ; } } for (k = array ->size; k >j; k--) { array ->data[k] = array ->data[k-1 ]; } array ->data[j] = x; array ->size++; return true ; }
注意
1.审题,题中如果数组满了或者有插入的数字,就返回 false 。
2.插入一个数,必须要么每个数向前挪,要么向后挪。