作业信息
这个作业属于哪个课程 | 2024-2025-1-计算机基础与程序设计) |
---|---|
这个作业要求在哪里 | https://www.cnblogs.com/rocedu/p/9577842.html#WEEK07 |
这个作业的目标 | 数组与链表 基于数组和基于链表实现数据结构 无序表与有序表 树 图 子程序与参数 |
作业正文 | https://www.cnblogs.com/tanzitian11/p/18537336 |
教材学习内容总结
计算机科学与概论
1. 抽象数据类型与子程序
1.抽象数据类型:抽象数据类型(Abstract Data Type,简称 ADT)是指一个数学模型以及定义在该模型上的一组操作。它是对数据类型的一种抽象描述,只关注数据的逻辑特性和操作,而不考虑具体的实现细节。
2. 数据结构:是一种存储和组织数据的方式,以便能够高效地访问和操作数据。它不仅涉及数据的存储方式,还包括对数据进行的各种操作,如插入、删除、查找等。
3.容器:容器是一种存储和管理数据的对象,通常提供了一组操作来方便地插入、删除、查找和遍历数据。容器可以看作是一种更高层次的数据结构,它通常基于现有的数据结构实现,并提供了更方便的接口和功能。
4.队列:计算机队列是一种特殊的线性数据结构,遵循先进先出(FIFO,First In First Out)的原则。它在计算机科学的各个领域都有广泛的应用。
一、队列的组成
队头(front):指向队列中第一个元素的位置。
队尾(rear):指向队列中最后一个元素的下一个位置。
元素集合:存储在队列中的数据元素。
二、队列的基本操作
入队(enqueue):将一个元素添加到队列的队尾。
操作步骤:首先将队尾指针 rear 向后移动一个位置,然后将新元素放入 rear 所指的位置。
但在某些特殊情况下可能需要重新分配内存,此时时间复杂度可能为 O (n)。
出队(dequeue):从队列的队头删除一个元素。
操作步骤:取出队头元素,然后将队头指针 front 向后移动一个位置。
查看队头元素(peek):返回队列的队头元素,但不删除它。
判断队列是否为空(isEmpty):检查队列中是否没有元素。
判断队列是否已满(isFull):对于有固定大小的队列,检查队列是否已满。
5.列表:
一、概念
列表是一种常见的数据结构,它是由一组有序的元素组成。
二、特点
1.有序性
列表中的元素是按照特定的顺序排列的,这个顺序可以是插入的顺序,也可以是根据某种规则进行排序后的顺序。
你可以通过索引来访问列表中的特定元素,这使得在需要按照特定顺序处理数据时非常方便。
2.可变性
列表通常是可变的,这意味着你可以添加、删除或修改列表中的元素。
这种可变性使得列表在处理动态数据集合时非常有用,比如在用户输入不断变化的情况下。
3.多样性
列表可以存储不同类型的元素,比如整数、字符串、对象等。
这使得列表在存储和处理复杂数据结构时非常灵活。
6.树:
一、定义与基本概念
树是由 n(n≥0)个节点组成的有限集合。当 n = 0 时,称为空树。在一棵非空树中:
有一个特定的称为根(root)的节点。
当 n > 1 时,其余节点可分为 m(m > 0)个互不相交的有限集合 T1、T2、……、Tm,其中每一个集合本身又是一棵树,并且称为根的子树。
二、树的特点
层次性:树具有明显的层次结构,从根节点开始,逐渐向下分支形成子树。
非线性:与线性数据结构(如数组、链表)不同,树的节点之间不是简单的线性关系。
一对多关系:除了根节点外,每个节点有且仅有一个父节点,但可以有零个或多个子节点。
三、常见类型的树
二叉树:每个节点最多有两个子树的树结构。
满二叉树:所有叶节点都在同一层,并且每个非叶节点都有两个子节点。
完全二叉树:除了最后一层,其他各层的节点数都达到最大,并且最后一层的节点从左到右依次排列。
二叉搜索树:对于二叉搜索树中的任意一个节点,其左子树中的所有节点的值都小于该节点的值,右子树中的所有节点的值都大于该节点的值。
平衡二叉树:是一种特殊的二叉搜索树,它的左右子树的高度差不超过 1,以保证树的查找、插入和删除操作的时间复杂度为 O (log n)。
哈夫曼树:也叫最优二叉树,用于数据压缩等领域。它是带权路径长度最短的二叉树。
四、树的基本操作
插入节点:将一个新节点插入到树中的合适位置。在二叉搜索树中,根据节点的值与当前节点的值的比较结果,决定将新节点插入到左子树还是右子树。
删除节点:从树中删除一个指定的节点。删除节点的操作相对复杂,需要考虑被删除节点的位置和子树的情况。
查找节点:在树中查找具有特定值的节点。根据树的结构特点,可以采用不同的查找算法。
遍历树:遍历树是指按照一定的顺序访问树中的所有节点。常见的遍历方式有前序遍历、中序遍历、后序遍历和层次遍历
7.图:
一、定义与基本概念
图由顶点(vertex)和边(edge)组成。顶点也称为节点,边则是连接两个顶点的线段。如果边是有方向的,则称为有向图;如果边没有方向,则称为无向图。
二、图的表示方法
邻接矩阵:用一个二维矩阵来表示图。矩阵的行和列分别对应图中的顶点。如果两个顶点之间有边相连,则矩阵中对应的元素为 1(或边的权重);如果没有边相连,则元素为 0。
优点:可以快速判断两个顶点之间是否有边相连,以及获取边的权重。
缺点:对于稀疏图(边的数量相对较少的图),会浪费大量的存储空间。
邻接表:为每个顶点建立一个链表,链表中存储与该顶点相邻的顶点。
优点:对于稀疏图,存储空间效率高。
缺点:判断两个顶点之间是否有边相连需要遍历链表,相对较慢。
三、图的基本操作
插入顶点:向图中添加一个新的顶点。
插入边:在两个顶点之间添加一条边。对于有向图,需要指定边的起点和终点;对于无向图,边是双向的。
删除顶点:从图中移除一个顶点,并删除与该顶点相关的所有边。
删除边:从图中移除一条边。
遍历图:有多种遍历方式,如深度优先遍历和广度优先遍历。
深度优先遍历:从一个顶点开始,沿着一条路径尽可能深地探索,直到无法继续前进,然后回溯到上一个顶点,继续探索其他路径。
广度优先遍历:从一个顶点开始,先访问该顶点的所有相邻顶点,然后再依次访问这些相邻顶点的相邻顶点,直到遍历完整个图。
8.子程序:
一、定义与概念
子程序,也称为函数、方法或过程,是一段可重复使用的代码块,用于完成特定的任务。它可以接受输入参数(也称为自变量),并返回一个结果(如果有返回值的话)。
二、特点
代码复用:子程序的主要目的之一是实现代码复用。通过将一段常用的代码封装成子程序,可以在多个地方调用它,避免重复编写相同的代码。
模块化:子程序将复杂的任务分解为较小的、易于管理的模块。每个子程序专注于完成一个特定的功能,使得程序的结构更加清晰,易于维护和扩展。
参数传递:子程序可以接受输入参数,这些参数可以是不同类型的数据,如整数、字符串、对象等。通过参数传递,子程序可以根据不同的输入执行不同的操作。
返回值:子程序可以返回一个结果给调用者。返回值可以是任何数据类型,取决于子程序的功能。
三、作用与优势
提高开发效率:通过复用已有的子程序,可以减少开发时间和工作量。开发人员可以专注于编写新的功能,而不必重复实现已经存在的功能。
增强代码可读性:将复杂的任务分解为多个子程序,每个子程序具有明确的功能和名称,使得代码更易于理解和阅读。其他开发人员可以更容易地理解程序的逻辑结构,并进行维护和扩展。
便于调试和测试:由于子程序是独立的代码块,可以单独进行调试和测试。这有助于更快地发现和修复错误,提高程序的质量。
可维护性:当需要修改程序的功能时,如果该功能是通过子程序实现的,只需要修改相应的子程序即可,而不会影响到其他部分的代码。这使得程序的维护更加容易。
四、调用方式
直接调用:在程序中直接使用子程序的名称,并传递相应的参数来调用它。例如,在 Python 中,可以使用function_name(parameter1, parameter2)的方式调用一个函数。
间接调用:通过指针、引用或函数对象等方式间接调用子程序。这种方式在一些高级编程技术中经常使用,如函数指针、回调函数等。
五、参数传递方式
值传递:将参数的值复制一份传递给子程序。在子程序中对参数的修改不会影响到原始参数的值。
引用传递:将参数的引用(内存地址)传递给子程序。在子程序中对参数的修改会影响到原始参数的值。
指针传递:与引用传递类似,通过传递参数的指针来实现参数的传递。在子程序中可以通过指针间接修改参数的值。
c语言程序设计
循环控制结构:
在计算机编程中,循环控制结构是一种重要的控制结构,用于重复执行一段代码块,直到满足特定的条件为止。
一、常见的循环控制结构类型
for循环:
for循环通常用于已知循环次数的情况。它有三个部分:初始化部分、循环条件部分和迭代部分。
例如,在 C 语言中,for (int i = 0; i < 10; i++) { // 循环体 },这里初始化了一个变量i为 0,循环条件是i < 10,每次循环后i自增 1。
for循环在很多编程语言中都非常常见,如 Java、Python、JavaScript 等。
while循环:
while循环在执行循环体之前先判断条件,如果条件为真,则执行循环体;如果条件为假,则跳出循环。
例如,在 C 语言中,while (condition) { // 循环体 }。只要condition为真,循环就会一直执行。
while循环适用于不确定循环次数的情况,因为循环条件可以根据程序的运行情况动态变化。
do-while循环:
do-while循环先执行一次循环体,然后再判断条件。如果条件为真,则继续执行循环体;如果条件为假,则跳出循环。
例如,在 C 语言中,do { // 循环体 } while (condition);。
do-while循环至少会执行一次循环体,这在某些情况下非常有用。
二、循环控制的关键要素
循环条件:
循环条件是决定循环是否继续执行的关键。它通常是一个布尔表达式,当表达式的值为真时,循环继续执行;当表达式的值为假时,循环结束。
循环条件应该在循环的执行过程中能够被改变,否则可能会导致无限循环。
循环体:
循环体是循环控制结构中重复执行的代码块。它可以包含任何合法的编程语言语句,如赋值语句、条件语句、函数调用等。
循环体的执行次数取决于循环条件的判断结果。
循环变量:
在for循环和一些while循环中,通常会使用一个循环变量来控制循环的执行次数或遍历一个数据集合。
循环变量的初始值、更新方式和终止条件都是循环控制的重要组成部分。
例子:编程从键盘输入n,计算并输出1+2+3+……+n的值。
#include<stdio.h> int main(void) { int i,n; int sum=0; scanf("%d",&n); for(i=1;i<=n;i++) { sum=sum+i; } printf("%d",sum); return 0; }
一、计数循环的基本结构
在大多数编程语言中,计数循环通常使用for循环来实现。其基本结构如下:
for (初始化计数器; 循环条件; 更新计数器) {
// 循环体
}
初始化计数器:在循环开始之前,设置计数器的初始值。这个初始值通常是一个整数,表示循环的起始点。
循环条件:这是一个布尔表达式,用于判断是否继续执行循环。只要循环条件为真,循环就会继续执行;当循环条件为假时,循环结束。
更新计数器:在每次循环结束后,更新计数器的值。这个更新操作通常是递增或递减计数器,以控制循环的执行次数。
循环体:这是在循环中重复执行的代码块。它可以包含任何合法的编程语言语句,用于实现特定的任务。
二、计数循环的控制方法
设置正确的初始值和循环条件:
初始值应该根据具体的需求来设置,确保循环从正确的起点开始。
循环条件应该能够准确地控制循环的执行次数。例如,如果要执行循环 10 次,可以设置循环条件为计数器小于 10。
注意避免设置错误的初始值和循环条件,以免导致无限循环或循环次数不正确的问题。
选择合适的计数器更新方式:
计数器的更新方式可以是递增(如i++)或递减(如i--),具体取决于循环的需求。
如果要从某个值开始逐渐增加到另一个值,可以使用递增方式;如果要从某个值开始逐渐减少到另一个值,可以使用递减方式。
还可以根据具体情况选择其他的更新方式,如每次增加或减少一个特定的值。
控制循环体中的操作:
在循环体中,可以执行各种操作,但要注意这些操作不要影响循环的控制条件。
例如,如果在循环体中修改了计数器的值,可能会导致循环的执行次数不正确。
确保循环体中的操作是合理的,并且不会破坏循环的控制逻辑。
考虑循环的退出条件:
除了循环条件之外,还可以在循环体中设置其他的退出条件。例如,如果在循环过程中满足了某个特定的条件,可以使用break语句立即退出循环。
这样可以在必要时提前结束循环,提高程序的效率。
一、嵌套循环的基本结构
以下是在大多数编程语言中嵌套循环的一般形式:
for (外循环初始化; 外循环条件; 外循环更新) {
// 外循环体
for (内循环初始化; 内循环条件; 内循环更新) {
// 内循环体
}
}
在这个结构中,外循环控制着整个嵌套循环的执行次数,而内循环在每次外循环迭代中都会完整地执行一遍。
二、嵌套循环的特点
执行顺序
嵌套循环的执行顺序是先执行外循环的一次迭代,然后在该迭代中执行内循环的所有迭代。接着,外循环进行下一次迭代,再次执行内循环的所有迭代,以此类推。
例如,如果外循环执行 3 次,内循环执行 4 次,那么内循环体总共会执行 3×4 = 12 次。
循环变量的作用域
外循环和内循环可以有各自独立的循环变量,它们的作用域分别在各自的循环体内。
但是,在一些编程语言中,如果不小心使用了相同的变量名,可能会导致变量冲突和错误的结果。
控制流程
可以在嵌套循环中使用break和continue语句来控制循环的执行流程。
break语句可以立即退出当前循环(内循环或外循环,具体取决于其在哪个循环中使用)。
continue语句可以跳过当前循环的剩余部分,直接进入下一次迭代。
一、条件控制循环的基本结构和原理
条件控制的循环通常使用while循环或do-while循环来实现。其基本结构如下:
while循环:
while (条件表达式) {
// 循环体
}
在while循环中,首先判断条件表达式的值。如果条件表达式为真,则执行循环体中的代码;然后再次判断条件表达式的值,重复这个过程,直到条件表达式为假为止。
do-while循环:
do {
// 循环体
} while (条件表达式);
do-while循环与while循环类似,但它会先执行一次循环体,然后再判断条件表达式的值。如果条件表达式为真,则继续执行循环体;否则,循环结束。
二、条件表达式的重要性
条件表达式是条件控制的循环的核心部分,它决定了循环是否继续执行。条件表达式通常是一个布尔表达式,其结果为真或假。在编写条件表达式时,需要考虑以下几个方面:
初始条件:在进入循环之前,需要确保条件表达式的初始值为真,否则循环将不会执行。
循环更新:在循环体中,需要确保对条件表达式的值进行更新,以便在适当的时候结束循环。如果条件表达式的值始终为真,将会导致无限循环。
边界条件:需要考虑循环的边界条件,以确保循环在正确的情况下结束。例如,如果循环是用于遍历一个数组,需要确保在到达数组末尾时结束循环。
流程的控制与转移
跳转语句
break语句:
用于跳出循环或switch语句。
例如,在循环中,当满足某个条件时,可以使用break跳出循环:while (true) {if (condition) {break;} }。
continue语句:
用于跳过当前循环的剩余部分,直接进入下一次循环。
例如,在循环中,当满足某个条件时,可以使用continue跳过本次循环:while (i < 10) {if (i % 2 == 0) {continue;} printf("%d ", i); i++;}。
goto语句:
可以无条件地跳转到程序中的某个标签处。但由于goto语句会使程序的流程变得混乱,难以理解和维护,所以一般不推荐使用。
例如:goto label;... label: printf("跳转到此");。
结构化程序设计的核心思想
一、自顶向下
含义
从程序的总体功能出发,将一个复杂的问题逐步分解为若干个较小的子问题,然后再对每个子问题进行进一步的分解,直到问题变得足够简单,可以直接用程序语句来实现。
这种方法使得程序员能够更好地理解和把握整个程序的结构和逻辑,从而提高程序的可读性、可维护性和可扩展性。
示例
例如,要开发一个学生成绩管理系统,可以先将其分解为学生信息管理、课程信息管理、成绩录入、成绩查询等几个子模块。然后,再对每个子模块进行进一步的细分,如学生信息管理可以分为学生信息录入、学生信息修改、学生信息删除等功能。
二、逐步求精
含义
在自顶向下分解问题的过程中,对每个子问题进行逐步细化,不断增加细节,直到可以用具体的程序语句来实现。
这种方法可以帮助程序员避免一开始就陷入细节,从而更好地把握程序的整体结构和逻辑。
示例
以学生信息录入功能为例,可以先确定需要录入的学生信息包括姓名、学号、性别、年龄等基本信息。然后,再考虑如何输入这些信息,如何进行数据验证,如何存储这些信息等细节问题。
三、模块化
含义
将程序分解为若干个独立的模块,每个模块完成一个特定的功能。模块之间通过接口进行交互,模块内部的实现细节对其他模块是隐藏的。
这种方法可以提高程序的可维护性和可扩展性,因为当需要修改某个功能时,只需要修改相应的模块,而不会影响其他模块。
示例
在学生成绩管理系统中,可以将学生信息管理、课程信息管理、成绩录入、成绩查询等功能分别封装成不同的模块。每个模块都有自己的输入、输出和处理逻辑,模块之间通过函数调用或参数传递进行交互。
四、限制使用 goto 语句
含义
goto 语句可以无条件地跳转到程序中的任何位置,这会使程序的流程变得混乱,难以理解和维护。因此,结构化程序设计主张限制使用 goto 语句,尽量使用顺序、选择和循环三种基本控制结构来构造程序。
示例
例如,在 C 语言中,可以使用if语句、switch语句、while循环、for循环等控制结构来实现程序的流程控制,而避免使用goto语句。
基于AI的学习
代码调试中的问题和解决过程
-
问题1:求最大公约数的时候忘记公式了
int gcd(int a,int b)
{
if(b==0){
return a;
}else {
return gcd(b,a%b);
} -
问题1解决方案:又回去复习了辗转相除法。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第四周 | 200/200 | 1/2 | 20/20 | |
第五周 | 300/500 | 1/4 | 18/38 | |
第六周 | 500/1000 | 1/7 | 22/60 | |
第七周 | 300/1300 | 1/9 | 14/90 |