C博客作业04--数组

这个作业属于哪个班级 C语言--网络2011/2012
这个作业的地址 C博客作业04--数组
这个作业的目标 学习数组相关内容

0.展示PTA总分

  • 数组

  • 字符数组


1.本章学习总结

1.1 学习内容总结

1.1.1 知识点梳理

一维数组

  • 定义

    类型名 数组名 [数组长度];

    • 注意:数组长度是一个常量
  • 引用

    数组名 [下标]

    • 注意:下标可以是整型表达式,合理取值范围为[0,数组长度-1]

      ​ 不要让下标越界

  • 初始化

    类型名 数组名[数组长度」{初值表}

    • 注意:只有静态存储的数组才能初始化
  • 使用

    将数组的下标作为循环变量,通过循环可以对数组的所有元素进行处理

    输入:
    for(i=0;i<n;i++)
    {
       scanf("%d",&a[i]);
    }
    输出:
    for(i=0;i<n;i++)
    {
        printf("%d",&a[i]);
    }
    

二维数组

  • 定义

    类型名 数组名[行长度][列长度];

  • 引用

    数组名[行下标][列下标]

    • 注意:行下标的合理取值范围为[0,行长度-1],列下标的合理取值范围为[0,列长度-1]

      ​ 按行→列的方式存放,先存放第0行的元素

  • 初始化

    • 分行赋初值

    类型名 数组名[行长度][列长度]={{初值表0},……,{初值表k},……};

    • 顺序赋初值

类型名 数组名[行长度][列长度]={初值表};

  • 使用

    将二维数组的行下标和列下标分别作为循环变量,通过二重循环可以遍历二维数组。将行下标作为外循环的循环变量,列下标作为内循环的循环变量。

    输入:
    for(i=0;i<n;i++)
    {
       for(j=0;j<n;j++)
       scanf("%d",&a[i][j]);
    }
    
    输出:
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        printf("%d",&a[i][j]);
    }
    
  • 例题:

    • 杨辉三角

      注意:判断哪个几个地方用“1”表示,找出数字之间的关系

    • 判断是否为上三角矩阵

      注意:输出YES/NO是在循环内,判断上三角的条件

      术语 含义 下标规律
      主对角线 从矩阵的左上角至右下角的连线 i==j
      上三角 主对角线以上的部分 i<=j
      下三角 主对角线以下的部分 i>=j
      副对角线 从矩阵的右上角至左下角的连线 i+j=N-1
    • 二维数组每列排序(题目要求:每一列按从小到大的顺序排列且每行的每个数之间有一个空格)

      注意:注意输出要换行!!在条件控制中,是在控制列的情况下,每列中的数字两两进行比较。用m变量标为下一个数字,如果后面的 数字大则要换位置。


字符数组

  • 字符串

    一串字符,它的结束标志时'\0',字符串的有效长度就是有效字符的个数

  • 存储--赋值和输入

    • 注意:区分"a"和'a'

      ​ 前者是字符串常量,包括'a'和'\0'两个字符,用一维字符数组存放

      ​ 后者是字符常量,只有一个字符,可以赋给字符变量

  • 字符串的输入

    • 格式化输入:

      scanf("%s",str) 当输入字符串时输入'\n'、 ' '时停止录入并且会自动在输入字符后加上'\0'的结束符标志

    • 循环输入:

      while((str[i]=getchar())!='\n')
      i++;
      str[i]='\0'
      
      ...
      
      for(i=0;str[i]!='\0';i++)
      ...
      
      • 注意:用结束符'\0'控制循环,不能省略!!!否则字符串就不能正常结束
    • 函数输入:fgets()函数

      读取文件当中的n-1个字符到s中,从标准输入流中读取字符串,输入的字符个数超出了字符数组的大小不会导致溢出问题。且读取到换行符、文件尾或读完n-1个字符结束。但输入字符长度少于n-1,会多带一个换行符

      fgets(数组名,数组数,stdin) 当输入字符串时输入'\n'结束录入并且会将回车键录入,后在其末尾加上'\0'的结束符标志


1.1.2 知识点技巧总结

查找数据

  • 顺序查找法

    将数存入数组,再输入一个数x,在数组中一个一个查找,看是否有相同的数存在,存在即输出相应的下标。

for(i=0;i<n;i++)
{
if(a[i]==x)//如果在数组a中找到了x
  {
      printf("index is %d",i);//输出相应下标
      
  }
  • 二分查找法

    首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

    基本思想:将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.时间复杂度即是while循环的次数。

public static int Method(int[] nums, int low, int high, int target)
        {
            while (low <= high)
            {
                int middle = (low + high) / 2;
                if (target == nums[middle])
                {
                    return middle;
                }
                else if (target > nums[middle])
                {
                    low = middle + 1;
                }
                else if (target < nums[middle])
                {
                    high = middle - 1;
                }
            }
            return -1;
        }

插入数据

  • 插入排序

在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序

img

简化的插入排序(N给出的数 X需要插入的数 从小到大有序排列,每个数字后有一个空格):


删除数据

  • 数组元素的删除

伪代码:

定义数组a[100]
定义变量k //表示进行删除的次数
定义变量n //表示输入的数组元素个数
定义变量m//表示需要删除的数字
定义变量flag//用于储存删除次数

输入n
输入数组a[]
输入删除次数k
while(k--)//循环次数减少
  输入变量m
  for(i=m-1;i<n;i++)//如果该数字为被删除的数字的前一个数字,则前一个数字需要往前挪
      a[i]=a[i+1]
end while

/*输出*/
for(i=0;i<n-flag;i++)//循环到删除次数结束
      if(i == n - flag - 1)//删除次数结束
         输出数组最后一个数a[i]
      else
         输出a[i]’空格‘
end for
  • 删除数字字符

伪代码:

定义字符串str[1000]
定义变量i 控制循环
定义变量k 控制循环//注意!k=0!!!

输入字符串
for(i=0;str[i]!='\0';i++)
   if(str[i]<'0'||str[i]>'9')//如果该字符串中没有数字
      str[k]=str[i]//重新建立一个字符串,用k来存储非数字的字符
      k++
   end if
end for
/*输出*/
for(i=0;i<k;i++)
   输出字符串str[i]
end for
  • 删除重复字符

    伪代码:

    定义字符数组a[256]代表出现的次数//ASCII
    定义变量ch存储字符
    定义变量i控制循环次数
    while ((ch = getchar()) != '\n')
       a[ch]++;   //以字符的形式,修改出现的字母
    end while
    for (i = 0;i < 256;i++)
       if a[i] != 0   //如果对应单元不为0,说明需要输出
          输出i;
       end if
    end for
    

排序方法

  • 冒泡排序法

从头到尾比较相邻的元素,若前大则与后进行交换。

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

img

伪代码:

定义变量n存储数组单元个数,k表示扫描的遍数(依题意)
定义数组num[100]存储输入的变量
定义i,j控制循环,temp用于交换
定义cnt 计算交换次数
输入n,k
输入数组num
for(i=0;i<n;i++)//重复操作,直到排序完成
  for(j=0;j<n-i-1;j++)//对每一对相邻元素比较大小
     if(num[j + 1] < num[j])//比较相邻元素,如果前一个比后一个大,就交换
          交换...
     end if
  end for
end for
输出数组num
  • 选择排序法

要排序的一组数中,选出最小(或最大)的一个数与第一个位置的数交换;在剩下的数当中找最小的与第二个位置的数交换,即顺序放在已排好序的数列的最后,如此循环,直到全部数据元素排完为止。

img

伪代码:

定义数组num[10]存储输入的变量
定义变量n表示给出的数的数量
定义变量i,j控制循环
定义temp用于交换
定义index记录需要交换的下标
输入n
输入数组num
for(i=0;i<n;i++)
   index=i;
   for(j=i+1;j<n;j++)
     if(num[j]>num[j+1])
        index=j
     end if
   end for
   交换...
 end for
 输出数组num

哈希数组用法

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

用一个数组的下标与输入的数据关联起来,再将输入数据与数组下标进行对照。将字母与数组的下标一一对应,对输入数据进行判断,但判断符合时,对应变量num[i]++。


2.PTA实验作业

2.1 数组循环左移

本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,即将a中的数据由(a​0a1⋯an−1 )变换为(a​m ⋯an−1a​0a1⋯a​m−1)(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

2.1.1 伪代码

定义n,m//n为数组长度,m表示移动的次数
定义变量i 控制循环
定义变量loc 
定义数组a[100]

输入n,m
if(n>=m)
  loc=n-m//如果n大于m 下标相减
else
  loc=n-m%n//如果n小于m 则除余后相减
 /*输入*/
for(i=0;i<n;i++)
  m=loc%n//从第一个不需要移动的数字开始输入数组
  输出新数组
  loc++
end for
/*输出*/
for(i=0;i<n;i++)
  if(i==0)
    输出数组第一个数a[i]
  else
    输出a[i]’空格‘
end for

2.1.2 代码截图

2.1.3 提交列表

一开始拿到这道题,确实没什么思路,不知道如何用算式来对数组前n位数进行移动。有参考网上的做法,将数字前几位进行取余操作,能够分离出需要移动的数字。

2.1.4 代码比较

  • 伪代码:

    for k=1 to m
       for i=1 to n-1
          数组左移一个位置
    	  第一个数放在最后一个位置
       end for
    end for
    
  • (老师的代码)代码截图:

  • 区别:

    首先,老师采用了封装函数,使代码更加简洁方便。其次,老师采用的思路更加容易理解。对数据的处理,并没有对前几位进行取余再移动而是采用了前后移动。感觉自己写复杂化了...

2.2找鞍点

一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

本题要求编写程序,求一个给定的n阶方阵的鞍点。

2.2.1 伪代码

定义变量n//n行n列
定义i,j控制循环
定义二维数组a[6][6]
定义列row
定义行line
定义flag//标注是否有鞍点
输入n
/*输入矩阵(两层二维)*/
for(i=0;i<n;i++)
   for(j=0;j<n;j++)
       scanf("%d",a[i][j])
   end for
end for

for(i=0;i<n;i++)
   for(j=0;j<n;j++)
      if(a[i][j]>=a[i][line])//找出行的最大值,行不会改变列
        line=j
      end if 
   end for
end for
   flag=1
for(row=0;row<n;row++)//每行中的最大值与所对应的列进行比较
   if(a[row][line]<a[i][line])
     flag=0
   end if
end for
 
if(flag==1)
  ...
else
  None

2.2.2 代码截图

2.2.3 提交列表

首先,根据题目要求需要找出该行上最大、在该列上最小,则这题显然要使用二维数组控制行和列的变化。在提交列表中,多种错误既有段错误、答案错误、格式错误。段错误是在控制row的时候最大值和最小值弄错了。 if (a[i][j] >= a[i][line])在这条语句中,没有加上等号,因为可能存在有并列极值元素,最后一个是鞍点的情况。

2.2.4 代码比较

  • 伪代码:

    输入二维数据
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)//找当前i行最大值下标maxIndex
    	for(j=0;j<n;j++)
    	{
    	  判断是否a[j][maxIndex]<a[i][maxIndex]
    	  有,则a[i][maxIndex]不是鞍点,退出循环
    	 }
    	 没有,则a[i][maxIndex]是鞍点,输出,退出循环
    }
    if(?)
    {
    说明没有提前退出循环,没有鞍点
    }
    
  • (老师的代码)代码截图:

  • 区别:

    学习老师的函数封装!但大体上思路是差不多的,先找到每行的最大值,再找最小值,进行比较,也使用了flag/maxIndex来储存鞍点所在的下标

2.3 切分表达式

四则运算表达式由运算数(必定包含数字,可能包含正或负符号、小数点)、运算符(包括+、-、*、/)以及小括号((和))组成,每个运算数、运算符和括号都是一个token(标记)。现在,对于给定的一个四则运算表达式,请把她的每个token切分出来。题目保证给定的表达式是正确的,不需要做有效性检查

2.3.1 伪代码

定义字符串str[50]
定义变量i 控制循环
定义flag 

输入字符串fgets
for (i = 0; str[i] != '\n'; i++)
  if(第一个地方就是第一个字符是正负号时)
  end if
  if(如果是数字或者小数点的话判断下一位是否是小数点或者数字)
  end if
  else if(负数的判断 前一位是数字还是其他符号)
  else if(正数的判断 数字前一位是不是‘(’)
end for

2.3.2 代码截图

2.3.3 提交列表

碰到符号换行输出?碰到数字,小数点直接输出?数字什么时候结束?正负符号?格式错误是因为 str[i] != '\n',而不是str[i] != '\0'

2.3.4 代码比较

  • 伪代码:
if str[i]是'('或')'或'*'或'/’
   找到token,换行输出str[i]
if str[i]是数字或小数点:
   if后一位是数字或小数点:
	  输出数字,不换行
   else
   输出数字,数字token在这里结束,再输出换行
if str[i]是'+'或'-'
	if i==0或 前一位是'(':
		str[i]是正负符号,直接输出,不换行
	else
		是token,换行输出str[i]
  • (老师的代码)代码截图:
  • 区别:

老师将算式分为运算符、数字、正负号。注意:运算符可以直接换行输出,数字需要判断该数字的前一个数是数字还是小数点,这些都是输出,不换行。判断+- 是要区分是运算符号还是正负号。获取每个字符的前后字符str[i-1]、str[i+1]提前结束本次循环,无需进入不必要分支,提高效率,'+''-'是正负符号字符。老师的代码比较清晰,相比之下我的代码就比较繁琐。


posted @ 2020-12-13 18:28  GGGa-Yi  阅读(381)  评论(0编辑  收藏  举报