zoukankan      html  css  js  c++  java
  • C语言博客作业04数组

    0.展示PTA总分

    0.1.一维数组

    0.2.二维数组

    0.3.字符数组


    1.本章学习总结

    1.1 学习内容总结

    一维数组.

    定义.
    类型标识符 数组名[常量表达式]
    说明.

    • 数组名的命名规则与变量名的命名规则一致
    • 常量表达式表示数组元素的个数。可以是常量或符号常量,不能为变量

    初始化.

    • int a[5]={1,2,3,4,5}
    • int a[6]={1,2,3} (未被初始化的后面的元素被系统自动赋值为0)
    • int a[9]={0}

    二维数组.

    定义.
    类型表示符 数组名[表示行数的表达式][表示列数的表达式]
    说明.
    行数可以不说明,但是一定要说明列数
    初始化.

    • int a[2][3]={1,2,3,4,5,6}
    • int a[2][3]={ {1,2,3},{4,5,6} }

    字符串数组.

    定义.
    char 数组名[数据长度]
    说明.
    字符型数据是以整数形式(ASCII代码)存放的,因此也可以用整型数组来存放字符数据。
    初始化.
    char a[8]={'i','l','o','v','e','y','o','u'}

    数组查找数据.

    • 遍历数组,用if语句判断数组中的数是否与寻找的数字相等。
    • 灵活使用flag,判断有无需要查找的数组。
    定义数组变量a[10]用来储存输入10个之内的数字
    定义变量x用来储存需要寻找的数字
    定义变量flag=0用来判断有无需要寻找的数字
    for int i=0 to 10 do i++
        if(a[i]==x) then 
            flag=1 //找到x,flag重新赋值用以输出找没找到
            break //找到X,就跳出循环,减少运行时间
        end if
    end for
    if(flag==1) then 
        输出“找到了”
    else   //flag初始化为0,如果if条件不满足不会进入下面的语句,flag的值一直为0 
        输出“没找到”
    end if
    

    数组插入数据.

    • 该题的前提是有序数组(从大到小或者是从小到大),首先找到插入的位置,因为是遍历数组,只要判断插入的数字大于(或者小于)数组中的数字即可,找到插入的位置后,break结束循环。
    • 将数组从最后一个数字开始往后挪(不能从插入位置开始往后挪,因为把每个数字往后移一个后,原来该位置上的数字就会被顶替掉,数据会丢失)。
    • 再将X赋值给插入的位置。
    定义数组变量Num[n]用来储存输入的有序数列
    定义变量X用来储存插入的数字
    for int i=0 to n do i++ 
        if(a[i]>X) then  //假设该数列是从小到大的排序,如果是从大到小排序的数列,判断条件为a[i]<X
            break //找到插入位置就退出循环,这个时候就不在对i做任何运算要确保i为插入数字的位置
        end if
    end for
    for int j=n-1 to i do j-- (这里的i也要进行后移)
        a[j+1]=a[j] //因为这里要插入一个数,定义数组的时候尽量大一点,防止越界
    end for
    a[i]=X //完成后移的循环后,i位置上的数字就空了用来把X放在该位置上
    输出插入X数字的"a[i]"数组
    

    数组删除数据.

    • 两个数组删除数据,一个数组储存输入的数据,另一个数组储存删除后的数据。
    • 一个数组删除数据,在输入数据的数组中做变换。

    两个数组删除数据.

    定义数组Num1[n]用来储存输入的数字
    定义数组Num2[n]用来储存删除数据后的数字
    定义变量X用来储存要删除的数字
    for int i=0 to n do i++
        if(Num1[i]!= X)then
            Num2[(int j=0)++]=Num1[i] //把不要删除的数字储存到Num2数组中
        end if
    end for
    输出删除X数字的"Num2[j]"数组
    

    一个数组删除数据.

    定义数组变量a[n]用来储存输入的数字
    定义变量X用来储存删除的数字
    for int i=0 to n do i++
        if(a[i]==X) then //如果数组中的元素有要删除的数字,就把后面的元素依次向前移一个位置,这样就可以把那个需要删除的数字顶掉
            for int j=i to n do j++
                a[i]=a[i+1] 
            end for
        end if
    end for
    输出删除X数字的"a[i]"数组
    

    注解
    两种代码各有优劣,只使用一个数组来删除数据,可以减少一个数组变量,整个代码的内存可以减少,但是这种方法也容易出错,使用不恰当会丢失后面的数据,替换的时候容易出错(像数组的倒序一样);使用两个数组删除数据比一个数组要更容易一点,这种方法的代码只需要遍历输入的数组,判断是否与要删除的数字相等,不相等就存进另一个数组。我个人更偏向二个数组的方法,简单明了。


    排序方法.

    • 选择法排序:每一次内层循环找到最值,记录最值所在位置的下标,内层循环结束后,交换最值所在的位置和外层循环当前所在的位置。
    • 冒泡法排序:相邻两个数字依次做比较,并做交换,每一次内循环的结果就是把最大的数排列在数组的最后面。

    选择法排序.
    代码1

    代码2

    运行结果1

    运行结果2

    注解
    两个代码的功能是一样的,但是代码二的运行时间会更长,因为它会把前面的数大于后面一个的数字进行交换,交换一轮循环。其实这样的循环完全没必要,这种循环更像是冒泡法排序的方法,最大的数经过一轮循环后在最后面。消耗的时间更多。代码一是直接找到最小数的下标,结束内层循环后再进行交换,也就是说代码一的内层循环只是用来寻找最小数所对应的下标,不进行任何的赋值计算,这样运行更快。代码二是我之前自己打PTA的时候写的代码,看过书之后就知道代码一的优化功能了,所以编程技巧要慢慢的学到后面去掌握以及每一个程序的优化。

    冒泡法排序.
    代码

    运行结果

    两种排序法的区别
    不同:冒泡法顾名思义就是把最大的数沉在底下,最小的浮在上面,每一次循环都要进行交换;选择法是在冒泡法的基础上进行简化,它不着急交换,只是记录最值的位置,在外层循环才来交换。这样的简化可以减少运行时间。
    相同:都是用来排序的方法;两者都是要逐个比较的,找出最值。


    数组做枚举用法.

    数组的下标是从0开始累计加一和枚举变量一样,枚举变量中是默认第一个变量的数值为0,之后的变量依次累加1。所以可以用枚举的方式表达数组的下标。

    (忽略这些红色的线条,VS不支持这个没得法,但是代码本身没有错!!!)


    哈希数组.

    哈希表,是根据关键码值而直接进行访问的数据结构。也是就说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度(来自百度)。我不是很懂这个哈希算法是啥,有点无助.....老师发布的题集里面好像有一道重复数据的题目:要将一个数组的元素作为另一个元素的下标。


    1.2 本章学习体会

    学习感受.

    老师在讲数组这一章之前,我把课本以及慕课翁恺老师的视频反反复复的看,看了三天左右,颗粒无收,能看懂老师写的代码,也能看懂课本上的代码,但是自己写不出来。(可能是本人的脑子原因,不知道为什么当时咋都不明白数组的使用,现在想想都觉得自己那个时候挺傻的。)数组的用法很广泛,在结构里面用的也比较多。数组相当于一个容器,依次把你输入的数据有序的储存出来,当你要使用它时候,用对应的下标表达即可。从数组开始,一直到后面的指针、结构、链表等等,这些内容都是C语言的灵魂(借用林老师的话)。我最直观的感受就是:C语言的大门从数组开始才是真正意义上打开了。前面所学的一切都是在为后面的精华做准备。不得不说,编程语言有一种魔力。在我没有接触它之前,编程语言离我很遥远,不选择关于计算机方面的专业,我怕是会离它远远的,但是现在,我拜倒在它的石榴裙下,它把我征服了。当时我看不懂数组的时候,内心慌得一批,恐惧了。但是怎么说呢,既然是人编的东西,那我们肯定就能看懂,我硬着头发去阅读了一些别人的写的规范的代码,找到了其中的秘诀,后面就慢慢的顺了。其实不只是数组,后面的难的内容,不是我看个一两遍就会的,这可能算是正常的,但是千万不要灰心,看不懂就一直看,不丢人,看到懂为止。中国人的阿Q精神是很强大的。很喜欢一句话,哪有什么天才,不过是百分之九十九的汗水加百分之一的天赋。既然选择远方,便只顾风雨兼程

    代码量.


    2.PTA实验作业

    2.1 一维数组-数组循环左移

    2.1.1 伪代码

    定义一个数组a[n]用来储存输入的序列数字
    定义变量n用来储存输入的数字的总个数
    定义一个变量m用来储存移动的位数
    m=m%n //判断移动位数与输入总个数的关系
    if(m==n) then  //移动位数是总个数的整数倍
         原样输出"a[n]"数组
    else  //输出移动后的数组
        for int i=m+1 to n do i++
            依次输出数组元素"a[i]"
        end for
        for int i=0 to m do i++
            输出剩下的数组元素"a[i]"
        end for
    end if
    

    2.1.2 代码截图

    2.1.3造测试数据

    2.1.4 PTA提交列表及说明

    Q1:没有考虑到m比n大导致一个测试点过不去。
    A1:直接加上m=m%n的表达式后是直接按移动后的数据输出。
    Q2:加上Q1的表达式后又忽略是m是n的整数倍的关系报错另一个测试点。
    A2:整个函数功能要分为两步,一个是m是n的整数倍关系原样输出,另一个是用取余表达式移动后的数据输出。使用取余表达式可以解决m与n大小的问题。

    2.1'二维数组-数组循环右移(与左移进行对比)

    2.1'.1伪代码

    定义一个数组a[7][7]用来储存输入的N阶数组
    定义一个数组b[7][7]用来储存右移后的数组
    输入右移M个位置和N阶方阵
    for int i=0  to n do i++
        for int j=0 to n do j++
            输入a[i][j]
        end for
    end for
    for i=0 to n do i++
        for j=0 to n do j++
            b[i][(j+M)%n]=a[i][j] //这里就要求我们找到右移的规律,只要找到规律就很快了,这也是数组的神奇之处!!!
        end for
    end for
    for i=0 to n do i++
        for j=0 to n do j++
            输出"b[i][j]"
        end for
    end for
    

    2.1'.2代码截图


    2.2 二维数组-螺旋方阵

    2.2.1 伪代码

    定义二维数组a[20][20]用来储存输入的方阵
    定义变量t=0用来累加赋值给方阵中的元素
    定义一个变量count=0用来计算方阵中元素改变的次数
    定义二维数组b[20][20]用来判断a[20][20]中数字有没有被替换
    for int i=0 to 20 do i++
        for int j=0 to 20 do j++
            b[20][20]初始化所有元素均为1
        end for
    end for
    输入n,表示是n阶方阵
    for i=0 to n do i++
        for j=0 to n dp j++
            b[n][n]赋值为0//表明这些元素要填入合适的数字
        end for
    end for
    for i=0 to n do i++ 
        for j=0 to n do j++ 
            b[n][n]赋值为0
        end for
    end for
    while(count< n*n) do
        while((int y=0) < n &&b[(int x=0)][y] ==0) do
            将t赋值给a[x][y]
            令b[x][y]为1//表明a方阵的该元素已经是被成功赋值了
            t++;y++;count++;
        end
        y--;x++
        while(y < n &&b[(int x=0)][y] ==0) do
            将t赋值给a[x][y]
            令b[x][y]为1//表明a方阵的该元素已经是被成功赋值了
            t++;x++;count++;
        end
        x--;y--
        while(y >=0 &&b[(int x=0)][y] ==0) do
            将t赋值给a[x][y]
            令b[x][y]为1//表明a方阵的该元素已经是被成功赋值了
            t++;y--;count++;
        end
        x--;y++;
         while(x >=0 &&b[(int x=0)][y] ==0) do
            将t赋值给a[x][y]
            令b[x][y]为1//表明a方阵的该元素已经是被成功赋值了
            t++;x--;count++;
        end
        x++;y++;
    end
    完成上述循环后,输出n阶螺旋方阵"a[n][n]"
    

    2.2.2 代码截图

    2.2.3造测试数据

    2.2.4PTA提交列表及说明

    这道题目,我出现的错误不止提交列表那么简单,我就不按照提交列表来说了。
    Q1:当时思路没有理清楚,输入出来的是行式S形方阵
    A1:我当时没找到螺旋方阵的规律,改了一种循环方式,输出来的又是列式S形方阵。
    Q2:继A1之后又是一番大改动,可是仍旧输出来的是别的类型方阵,还有一个循环越界了。
    A2:经历了N多次这样的大改动循环仍旧无故,然后我只能取百度了,借鉴别的优秀的代码,当时还没怎么明白那个螺旋的规律就开始去折腾自己的代码。
    Q3:是的,没错,输出的依然是乱七八糟的方阵,毫不夸张的说--乱七八糟,当时心里急得一批,脑子都炸了......就差撞豆腐了
    A3:错了总是要改错的勒,万能的度娘又来了,又是去网上找答案咯,看网上的代码,慢慢的知道螺旋的规律,就自己在纸上罗列了那个规律,慢慢的就把那个代码差不多快写出来了....
    .
    . 这处省略复杂的调试过程
    .
    部分正确:好不容易把样例的正确答案搞出来了,一提交,OMG,最大的N那个测试点过不了,那个心情真的是想用面条上吊啊!!!
    解决方式:我们的助教,隆重出场了,助教说,数组的大小写大一点,虽然题目的要求是小于10的N阶方阵,但是数组的范围大一点会比较好。所以把数组写为了20的范围,然后我又改了一个条件
    部分正确:之前的那个条件改错了,再加上没有把b[n][n]初始化为0导致的错误。
    解决方式:把前面两个错误修正,让b[n][n]赋值为0的原因是判断改位置是否填入对应的t。

    2.3字符串数组-大数加法

    2.3.1伪代码

    定义字符串数组a[1005]用来储存输入的其中一个相加的大数
    定义字符串数组b[1005]用来储存输入的另一个相加的大数
    定义数组a1[1005]用来储存倒序的数组a
    定义数组b1[1005]用来储存倒序的数组b
    定义数组c1[1005]用来储存两个数组中长度较长的倒序后的数组元素
    定义变量len1记录数组a的长度
    定义变量len2记录数组b的长度
    定义变量flag=0用来进位计算
    if(len1 > len2) then 
        for int i=0 to len1 do i++
            c[i] = c[i] + b1[i] + flag
            if(c[i] >= 10)
                c[i] = c[i] - 10
                flag=1//如果某一位相加超过十,则上一位对应加1
            else
                flag=0
            end if
        end for
        if ((c[len1 - 1] + b1[len1 - 1]) >= 10) then
            输出"1" //最高位超过十,输出1,不往数组里面写元素是怕会越界
        end if
        for i = len1 -1 to 0 do i--
            输出"c[i]"
        end for
    else
        for int i=0 to len2 do i++
            c[i] = c[i] + b1[i] + flag
            if(c[i] >= 10) then 
                c[i] = c[i] - 10
                flag=1//如果某一位相加超过十,则上一位对应加1
            else
                flag=0
            end if
        end for
        if ((c[len2 - 1] + b1[len2 - 1]) >= 10)
            输出"1" //最高位超过十,输出1,不往数组里面写元素是怕会越界
        end if
        for i = len2 -1 to 0 do i--
            输出"c[i]"
        end for
    end if
    

    2.3.2代码截图

    2.3.3造测试数据

    2.3.4PTA提交列表及说明

    Q1:当时那个进位那个地方的代码写错了,一旦有一个进位,之后的每一位数字都要加1
    A1:灵活定义一个flag=0;如果进入那个要进位的条件就让它等于1,这样下一组相加就会多加1。不满足进位条件仍旧为0,不影响下一组运算。
    Q2:最高位进位的测试点没有考虑完全,我把最高位进位放到那个数组最后一个元素+1里面了
    A2:如果加1就要放到数组中去,有可能会越界,之前没有考虑到这一方面的问题,所以在输出之前加一个条件,如果最高位也要进位,则另外输出1

    3.阅读代码

    代码问题:
    输入的N,K,分别表示的是N头牛,K以内的序列,后面输入N个牛所对应的ID,要求写一个代码帮农场主构造出的最短可能序列的长度,这个范围不是他的牛的广义ID的子序列。
    代码解析:

    • while循环条件那条语句使用的是EOF,关于这个EOF我也是前不久才知道的。EOF是End Of File的意思,在C语言中定义的一个宏,用作文件结束标志。从数值角度看,就是-1。这一条是我们可以学习的。
    • "#define clr(x)memset(x,0,sizeof(x))",这一条语句很特别,它的常量定义不像我们是直接一个数,该代码是直接宏定义,这样做可以不浪费数字。值得学习。
    • 整个代码给人一种很舒服的感觉,虽然可能看不懂代码的意思,但是代码本身的可读性还是很高的,这一点是林老师是第一堂课就强调的。
    • 代码的数组变量是全局变量。我们好像不敢去用数组的全局变量,害怕会崩盘,一旦发生错误可能会导致整个程序崩溃。但是数组的全局变量在某类题目上是很有用的,这就需要我们分辨是否选择全局变量了。但是我们还是要学习优秀代码的数组的全局变量。
  • 相关阅读:
    jython resources
    Installing a Library of Jython ScriptsPart of the WebSphere Application Server v7.x Administration Series Series
    jython好资料
    ulipad install on 64bit win7 has issue
    an oracle article in high level to descibe how to archtichre operator JAVA relevet project
    table的宽度,单元格内换行问题
    Linux常用命令大全
    dedecms系统后台登陆提示用户名密码不存在
    登录织梦后台提示用户名不存在的解决方法介绍
    Shell常用命令整理
  • 原文地址:https://www.cnblogs.com/springxinxin/p/11850807.html
Copyright © 2011-2022 走看看