C博客作业--指针

一、PTA实验作业

题目1:判断回文字符串

1. 本题PTA提交列表(要提交列表,不是结果)

2. 设计思路(伪代码或流程图)

伪代码:

函数传入数组名即地址,给形参s
定义ij为循环变量
for i=0 to s【i】!='\0'
end
i--
j=0
while (1)
    如果s【i】==s【j】首尾字符相等
        如果比较的字符相遇则停止循环
        i--
        j++
    否则 返回0 结束循环
end
返回1

流程图:

3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)

4.本题调试过程碰到问题及PTA提交列表情况说明。

答案错误
第一次没有考虑到奇数和偶数字符串的关系,结束循环的条件只写了ij时的情况,导致答案错误
解决方法:加了j
i+1的结束条件就可以了

题目2:求子串在母串中最后一次出现的地址

1. 本题PTA提交列表(要提交列表,不是结果)

2. 设计思路(伪代码或流程图)

传入数组s
定义循环变量i,j,mark用于比较子串,mark2记录地址,flag判断是否为子串
for i=0 to s【i】!=‘\0’
    mark=i记录比较开始的位置
    for j=0 to s【j】!=‘\0’
        如果该位置的字符与子串第一个相同比较下一个字符,都相同flag=0
        如果不相同flag=1
    如果flag==0,mark2记录i
end
如果mark2没有变化返回null
否则返回s【mark2】的地址

3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)

4.本题调试过程碰到问题及PTA提交列表情况说明。

答案错误
1.刚开始未有设计返回空指针,导致答案一直错误
解决方法:如果mark2没有被改变,表明没有找到过子串,所以这个时候就要返回空指针
2.只找到第一个出现子串的地址
解决方法:将程序设为反复查找,并写再一次找到的地址会覆盖掉第一次查找的地址,最后的结果就是最后的地址
3.返回地址的问题:刚开始习惯直接返回数组名,但是显然不行
解决方法:用&,取出s【mark】的地址

题目3:字符串串动变化

1. 本题PTA提交列表(要提交列表,不是结果)

2. 设计思路(伪代码或流程图)

传入数组p
定义循环变量i,max存最大ASCII码最大的字符,t由于交换,code存最大码的下标
max先取p【0】code取0
for i=1 to p【i】!=‘\0’
    if p【i】>max 将p【i】写入max,code保存i
end
先用t存p【code】即找到最大的字符
for i=code to 1
    code的字符右移
end
t存的字符给第一个字符

3.代码截图(注意,截图,截图,截图。不要粘贴博客上。不用用···语法去渲染)

4.本题调试过程碰到问题及PTA提交列表情况说明。


问题如图,字符e消失,而A多了一个,明显是交换时发生的错误
解决方法:最后t的值不应该给p【i-1】,因为上一轮循环,i最后跳出时有发生了递减,所以,我的做法是直接交给p【0】

二、截图本周题目集的PTA最后排名。

三、阅读代码

  • 猴子选大王
    让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。
#include<stdio.h>  
int main()  
{  
    int i, j, k, temp;  
    int monkey[1001];//总数不能大于1000  
    unsigned int n;  
    scanf("%d", &n);//输入猴子总数  
    for (i = 0; i < n; i++){  
        monkey[i] = i + 1;//给猴子排序,站成一排  
    }  
    for (i = n - 1; i >= 0; i--){  
        for (k = 1; k <= 3; k++){  
            temp = monkey[0];  
            for (j = 0; j < i; j++){  
                monkey[j] = monkey[j + 1];  
            }  
            monkey[i] = temp;  
        }  
    }  
    printf("%d", monkey[0]);//数组头就是猴王  
    return 0;  
}  

功能:选出猴王
优点:通常的思路是考虑下标移动和删除第三个位置,但是改代码思路新颖,不去考虑下标移动和删除,而是简单的做数组数字移动,巧妙的将数到3这个步骤替换成数组数据的移动3次,第3个数就会刚好排到数组尾,再在剩下的数之间移动,第3的数就会渐渐排到后面,最后数组头就是“猴王”。当初做这道题时感觉题目会很复杂,想了好久,一点思路都没有,关键是围成一个圈,数到最后还要接到数组头,然后上网查了很多很长的代码,直到找到这个代码,原来十几行就可以了。

  • 最大公共子串
    求两个串的所有子串中能够匹配上的最大长度是多少。
    比如:"abcdkkk" 和 "baabcdadabc",
    可以找到的最长的公共子串是"abcd",所以最大公共子串长度为4。
    下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。
#include <stdio.h>  
#include <string.h>  
  
#define N 256  
int f(const char* s1, const char* s2)  
{  
    int a[N][N];  
    int len1 = strlen(s1);  
    int len2 = strlen(s2);  
    int i,j;  
      
    memset(a,0,sizeof(int)*N*N);  
    int max = 0;  
    for(i=1; i<=len1; i++){  
        for(j=1; j<=len2; j++){  
            if(s1[i-1]==s2[j-1]) {  
                a[i][j] =a[i-1][j-1]+1; 
                if(a[i][j] > max) max = a[i][j];  
            }  
        }  
    }  
      
    return max;  
}  
  
int main()  
{  
    printf("%d\n", f("abcdkkk", "baabcdadabc"));  
    return 0;  
}

题目思路:
动态规划的思想,a[i][j]表示到字符串s1的i位置和s2的j位置的最大公共子串的长度 ,数组初始化为0。为了方便理解,我们这么想,如果s1的字符串的第一个字符和s2的第一个字符相同,那么a[1][1] = 1;如果两个字符串的第二个字符也相同,那么,到第二个位置的最长公共子串就等于1+1 = 2,也就是到第一个字符的公共子串的个数+1。即a[i][j] = 1+ a[i-1][j-1]。因此,我们可以从第一个位置开始递推求出到任意一个位置的公共子串,在递推过程中记录最大的结果即可。

优点:巧妙的运用二维数组,通过遍历,对每个位置子串长度做了统计和比较,大大节省了时间,同时具有极高的效率。

四、本周学习总结

1.自己总结本周学习内容。

1.使用指针基本应用
利用指针的移动,代替数组下标法提高程序效率
例:
冒号排序函数用指针代替

void bubble(int *a,int n)
{
    int *i,*j,t;
    for(i=1+a;i<a+n;i++){
        for(j=a;j<a+n-1;j++){
            if(*j>*(j+1)){
                t=*j;*j=*(j+1);*(j+1)=t;
            }
        }
    }
}

数组名即地址,定义两个指针,遍历数组只需指针的移动即可,下标法需要交换数组的数,指针则只要交换地址即可,效率远比下标法搞得多
2.数组与指针是相通的,数组就是const 类型的指针,不能随意修改,但是指针就可以
3.字符型指针,指针类型都是指向变量的类型,所以字符指针指向字符,当字符指针指向字符数组时,指针名即数组的首字符的地址,即p【0】等价于*str,p【i】等价于*(str+i)
4.字符串再C语言中会自动生成地址保存它们,所以字符串可以直接赋值给指针变量,即char *p=“string”;这个字符串叫做字符串常量。

2.罗列本周一些错题。

6-11 报数(20 分)
报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。
本题要求编写函数,给出每个人的退出顺序编号。

void CountOff( int n, int m, int out[] ){  
    int i=0,j=0,k=0,cnt=0,a[MAXN];  
    for(i=0;i<n;i++)  
        a[i] = i+1;
    i=0;  
    while(cnt < n){  
        if(a[i]!=0) k++;  
        if(k==m){  
            j++;  
            out[i]=j;  
            k=0;  
            cnt++;  
            a[i]=0;  
        }  
        i++;  
        if(i==n) i=0;  
    }  
} 

这道题想了很久都没有思路,上网查了一下,居然只有这么短。后来理解了这题,通过in时,i0将数组连成一个圈,将数到的数变成0而做到可以跳过这个数。

posted on 2017-12-13 20:48  斯慕  阅读(574)  评论(9编辑  收藏  举报