题目-----用键盘输入N个学生的姓名存储在字符数组中,并按字典顺序排序输出。
算法分析:
①定义一个二维数组,每行存储一个学生的姓名;若有10个学生则二维数组的行数为10。设姓名不超过15个字符,则二维数组的列数为15。
得设一个临时数组,一维的,用来交换的时候用。是一维的,因为每次只是交换一个字符串
②按字典顺序排序输出-----那么就是从a到z输出,从小到大
③选择排序的思想-----通过选择最大值的方法,依次将最大、第2大、第3大....
比如第一大,用第1个和后面的所有元素逐个比较,把最大的找出来
那么,接下来就是用第2个元素和后面的元素逐个比较,把第2大找出来
④输入的时候用gets(),因为姓名可能会有空格
⑤字符串比较用strcmp()函数,交换时赋值用strcpy()函数
我的代码:
1 #include <stdio.h> 2 #define N 5 3 int main(){ 4 5 int i,j; 6 char name[N][15]; 7 char Temp[15]; 8 for(i=0;i<N;i++){ 9 gets(name[i]); 10 } 11 12 for(i=0;i<N-1;i++){ 13 14 for(j=i+1;j<N;j++){ 15 if(strcmp(name[i],name[j])>0 ){ 16 strcpy(Temp,name[i]); 17 strcpy(name[i],name[j]); 18 strcpy(name[j],Temp); 19 } 20 } 21 22 } 23 24 25 for(i=0;i<N;i++){ 26 puts(name[i]); 27 } 28 29 }
分析:
我的的话交换时的算法就比较笨了,因为是每比较一次,如果大的话就要交换一次,一趟的话可能需要交换好几次,就会很影响程序的执行效率。
那么看看强者的代码
为了减少交换次数用k存储每趟比较中最小的字符串的小标,每趟最多交换一次
1 #include <stdio.h> 2 #define N 5 3 4 void main() 5 { 6 char name[N][15]; 7 char str[15]; 8 int i,j,k; 9 10 printf("请输入姓名:\n"); 11 for(i=0;i<N;i++){ 12 gets(name[i]); /*name[i]是行数组名 */ 13 } 14 15 printf("排序后的姓名:\n"); 16 for(i=0;i<N;i++){ 17 k=i; //k存储最小的字符串的下标 18 19 for(j=i+1;j<N;j++){ 20 if(strcmp(name[k],name[j])>0){ //最小则更新下标 21 k=j; 22 } 23 } 24 25 if(k!=i){ //将最小的字符串交换到i行 26 strcpy(str,name[i]); 27 strcpy(name[i],name[k]); 28 strcpy(name[k],str); 29 } 30 31 printf("%s\n",name[i]); //输出i行字符串并换行 32 } 33 }
总结:
19~23行是整个算法最妙的部分了 。刚开始还没有看明白,最后才发现,每次大的话,我就换成小的。那么最后的话,k里面存的就是最小的了
这样每次最多只用交换一次就可以了