实验五
一、实验结论
1、1. 设N个整数有序(由小到大)存放在一维数组中。编写函数binarySearch(),实现使用二分查找算法在一维数组中 查找特定整数item。如果找到,返回item在数组元素中的下标;如果item不在数组中,则返回-1。
方式①:形参是数组,实参是数组名,使用数组元素直接访问方式实现
1 // 练习:使用二分查找,在一组有序元素中查找数据项 2 // 形参是数组,实参是数组名 3 #include <stdio.h> 4 const int N=5; 5 int binarySearch(int x[], int n, int item); 6 int main() { 7 int a[N]={2,4,10,17,22};//已更改数组中整数 8 int i,index, key; 9 10 printf("数组a中的数据:\n"); 11 for(i=0;i<N;i++) 12 printf("%d ",a[i]); 13 printf("\n"); 14 15 printf("输入待查找的数据项: "); 16 scanf("%d", &key); 17 18 // 调用函数binarySearch()在数组a中查找指定数据项item,并返回查找结果给index 19 // 补足代码① 20 index=binarySearch(a,N,key); 21 22 if(index>=0) 23 printf("%d在数组中,下标为%d\n", key, index); 24 else 25 printf("%d不在数组中\n", key); 26 27 return 0; 28 } 29 int binarySearch(int x[], int n, int item) 30 { 31 int left=0,right=n-1,mid=n/2,i; 32 while(1) 33 { 34 if(item==x[left]) 35 return left; 36 37 if(item==x[right]) 38 return right; 39 40 if(item==x[mid]) 41 return mid; 42 43 for(i=0;item!=x[i];) 44 { 45 if(i>n-1) 46 { 47 return -1; 48 break; 49 } 50 i++; 51 } 52 53 if(item<x[mid]) 54 { 55 right=mid; 56 mid=(right+left)/2; 57 } 58 59 if(item>x[mid]) 60 { 61 left=mid; 62 mid=(right+left)/2; 63 } 64 65 } 66 67 }
不好意思,写到这里才发现已经把函数给出来只是让填空,下面补上所给子函数:
1 //函数功能描述: 2 //使用二分查找算法在数组x中查找特定值item,数组x大小为n 3 // 如果找到,返回其下标 4 // 如果没找到,返回-1 5 int binarySearch(int x[], int n, int item) 6 { 7 int low, high, mid; 8 low = 0; 9 high = n-1; 10 while(low <= high) 11 { 12 mid = (low+high)/2; 13 if (item == x[mid]) 14 return mid; 15 else if(item<x[mid]) 16 high = mid - 1; 17 else 18 low = mid + 1; 19 } 20 return -1; 21 }
方式②:形参是指针变量,实参是数组名,使用指针变量间接访问方式实现
1 // 练习:使用二分查找,在一组有序元素中查找数据项 2 // 形参是指针变量,实参是数组名 3 #include <stdio.h> 4 const int N=5; 5 int binarySearch(int *x, int n, int item); 6 int main() { 7 int a[N]={2,4,10,17,22}; 8 int i,index, key; 9 10 printf("数组a中的数据:\n"); 11 for(i=0;i<N;i++) 12 printf("%d ",a[i]); 13 printf("\n"); 14 15 printf("输入待查找的数据项: "); 16 scanf("%d", &key); 17 18 // 调用函数binarySearch()在数组a中查找指定数据项item,并返回查找结果 19 // 补足代码① 20 index= binarySearch(a,N,key); 21 22 if(index>=0) 23 printf("%d在数组中,下标为%d\n", key, index); 24 else 25 printf("%d不在数组中\n", key); 26 27 return 0; 28 } 29 30 //函数功能描述: 31 //使用二分查找算法在x指向的数据项开始的n个数据中,查找item 32 // 如果找到,返回其位置 33 // 如果没找到,返回-1 34 int binarySearch(int *x, int n, int item) { 35 int low, high, mid; 36 37 low = 0; 38 high = n-1; 39 40 while(low <= high) { 41 mid = (low+high)/2; 42 43 if (item == *(x+mid)) 44 return mid; 45 else if(item < *(x+mid)) 46 high = mid - 1; 47 else 48 low = mid + 1; 49 } 50 51 return -1; 52 }
结果同方式①,不再重复
2、使用选择法对字符串按字典序排序。不能直接使用关系运算符和赋值运算符,要借助字符串处理函数。
1 // 练习:使用选择法对字符串按字典序排序 2 #include <stdio.h> 3 #include <string.h> 4 void selectSort(char str[][20], int n ); // 函数声明,形参str是二维数组名 5 int main() { 6 char name[][20] = {"John", "Alex", "Joseph", "Candy", "Geoge"}; 7 int i; 8 9 printf("输出初始名单:\n"); 10 for(i=0; i<5; i++) 11 printf("%s\n", name[i]); 12 13 selectSort(name, 5); // 调用选择法对name数组中的字符串排序 14 15 printf("按字典序输出名单:\n"); 16 for(i=0; i<5; i++) 17 printf("%s\n", name[i]); 18 19 return 0; 20 } 21 22 // 函数定义 23 // 函数功能描述:使用选择法对二维数组str中的n个字符串按字典序排序 24 void selectSort(char str[][20], int n) { 25 // 补足代码 26 int i, j, k; 27 char temp[20]; 28 29 for(i=0; i<n-1; i++) { 30 k = i; // k用于记录当前最小元素的下标 31 32 for(j=i+1; j<n; j++) 33 if (strcmp(str[j],str[k])<0) 34 k = j; // 如果str[j]比当前最小元素还要小,就更新k,确保它总是存放最小元素的下标 35 36 if(k != i) { // 找到最小元素后,交换str[i]和str[k] 37 strcpy(temp,str[i]); 38 strcpy(str[i],str[k]); 39 strcpy(str[k],temp); 40 } 41 } 42 }
3、 用指针处理字符串
①:假定输入的字符串中只包含字母和*,例如字符串****A*BC*DEF*G*******。编写子函数 delPrefixStar(),删除字符串中所有前导*删除,中间的和后面的*不删除。即删除后,字符串的内容应当是 A*BC*DEF*G*******
1 // 用指针变量处理字符串练习1 2 // 删除前导* 3 #include <stdio.h> 4 void delPrefixStar(char []); // 函数声明(函数声明中可以省略数组名不写) 5 6 int main() { 7 char string[80]; 8 printf("输入一个字符串:\n"); 9 gets(string); 10 11 printf("\n删除<前导*>之前的字符串:\n"); 12 puts(string); 13 14 delPrefixStar(string); // 调用函数,删除前导*; 注意实参的写法 15 16 printf("\n删除<前导*>之后的字符串:\n"); 17 puts(string); 18 19 return 0; 20 } 21 22 // 函数定义 23 // 函数功能描述 24 // 删除字符数组s中前导* 25 void delPrefixStar(char s[]) { 26 char *target, *source; 27 28 // 从字符串开始找到不是*的位置 29 source = s; 30 while(*source == '*') 31 source++; 32 33 // 从这个位置开始将余下的字符前移 34 target = s; 35 while( *target++ = *source++); 36 }
②假定输入的字符串中只包含字母和*,例如字符串****A*BC*DEF*G*******。编写子函数 delStarButPrefix(),除了前导*之外,删除其它*。即删除后,字符串的内容应当是****ABCDEFG
1 // 用指针变量处理字符串练习2 2 // 删除中间和末尾的* (即除了前导*,删除字符串中其它全部*) 3 #include <stdio.h> 4 void delStarButPrefix(char []); // 函数声明(函数声明中可以省略数组名不写) 5 6 int main() { 7 char string[80]; 8 printf("输入一个字符串:\n"); 9 gets(string); 10 11 printf("\n删除<中间和末尾的*>之前的字符串:\n"); 12 puts(string); 13 14 delStarButPrefix(string); // 调用函数,删除中间和末尾的*; 注意实参的写法 15 16 printf("\n删除<中间和末尾的*>之后的字符串:\n"); 17 puts(string); 18 19 return 0; 20 } 21 22 // 函数定义 23 // 函数功能描述 24 // 删除字符数组s中除了前导*以外的所有*(即删除字符串中间和末尾出现的*) 25 void delStarButPrefix(char s[]) { 26 int i=0; // i用于记录字符在字符数组s中的下标 27 char *p = s; 28 29 // 跳过前导*,i记录字符在字符数组s中的下标,p记录首个非*字符的位置 30 while(*p && *p == '*') { 31 p++; 32 i++; 33 } 34 35 // 从p指向的字符开始,把遇到的*删除 36 while(*p) { 37 if(*p != '*') { 38 s[i] = *p; 39 i++; 40 } 41 p++; 42 } 43 44 s[i] = '\0'; // 思考:这一步这样写的原因 45 }
感觉可以把第30行改为while( *p == '*')
③假定输入的字符串中只包含字母和*,例如字符串****A*BC*DEF*G*******。编写子函数 delMiddleStar(),除了前导*和尾部*之外,删除中间出现的所有*。即删除后,字符串内容应当是 ****ABCDEFG*******
1 // 用指针变量处理字符串练习3 2 // 删除字符串中间的* 3 #include <stdio.h> 4 void delMiddleStar(char []); // 函数声明(函数声明中可以省略数组名不写) 5 6 int main() { 7 char string[80]; 8 printf("输入一个字符串:\n"); 9 gets(string); 10 11 printf("\n删除<中间的*>之前的字符串:\n"); 12 puts(string); 13 14 delMiddleStar(string); // 调用函数,删除字符串中间的*; 注意实参的写法 15 16 printf("\n删除<中间的*>之后的字符串:\n"); 17 puts(string); 18 19 return 0; 20 } 21 22 // 函数定义 23 // 函数功能描述 24 // 对字符数组s中存放的字符串,删除中间出现的* 25 void delMiddleStar(char s[]) { 26 int i=0; 27 char *tail, *head, *p; 28 29 // 找到末尾第一个非*字符的位置 30 tail = s; 31 while(*tail) 32 tail++; 33 34 tail--; 35 36 while(*tail == '*') 37 tail--; 38 39 // 找到开头第一个非*字符的位置 40 head = s; 41 while(*head == '*') 42 head++; 43 44 45 // 把中间出现的*去掉 46 p = s; 47 while(p<=head) { // 思考这里条件表达式为什么这样写,这个循环的功能? 48 s[i] = *p; 49 p++; 50 i++; 51 } 52 53 while(p<tail) { 54 if(*p != '*') { 55 s[i] = *p; 56 i++; 57 } 58 59 p++; 60 } 61 62 while(*p) { 63 s[i] = *p; 64 i++; 65 p++; 66 } 67 68 s[i] = '\0'; // 思考这里为什么要这样做 69 }
第48行可以删去,因为前导*未改变
二、实验总结与体会
1、二分查找算法
数组名作为参数: 形参是数组, 实参是数组名,直接访问各元素x[i];
指针变量作为参数:形参是指针变量,实参是数组名,间接访问*(x+i)等价于x[i]。(第20行第一次我写成了binarySearch(*a,N,key),而实参应为数组名)
2、选择法排序 使用选择法对字符串排序时注意事项 实验内容
与ex2_1.cpp不同的是,2_2是字符串的比较和赋值,不能直接使用关系运算符和赋值运算符,要借助字符串处理函数
3、使用指针变量对字符串进行处理 注意事项总结
3_2、3与3_1不同的是,并没有把最后一个'\0'赋值,需要再添单独加一个
https://www.cnblogs.com/astraeus/p/10906460.html
https://www.cnblogs.com/zys-0119/p/10898984.html
https://www.cnblogs.com/ssyxs/p/10912939.html