学期2024-2025-1 学号20241317 《计算机基础与程序设计》第十三周学习总结
作业信息
这个作业属于哪个课程 | <班级的链接>(如2024-2025-1-计算机基础与程序设计) |
---|---|
这个作业要求在哪里 | <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业) |
这个作业的目标 | <写上具体方面> |
作业正文 | https://www.cnblogs.com/manurios/p/18622472 |
教材学习内容总结
在《C语言程序设计》教材中,第十二章通常会介绍结构体以及基于结构体构建的简单数据结构。以下是这一章节可能包含的内容总结:
结构体(Structures)
- 结构体定义:介绍如何使用
struct
关键字定义结构体类型,包括如何声明结构体变量。 - 结构体初始化:讲解如何初始化结构体变量,包括直接初始化和使用
memset()
函数进行初始化。 - 结构体访问:使用
.
运算符访问结构体成员,以及如何通过指针访问结构体成员(使用->
运算符)。 - 结构体数组:创建和操作结构体数组,包括如何遍历和处理结构体数组。
- 结构体与函数:如何将结构体作为参数传递给函数,以及如何从函数返回结构体。
- 结构体嵌套:介绍结构体中可以嵌套其他结构体,以及如何访问嵌套结构体的成员。
枚举类型(Enumerations)
- 枚举定义:使用
enum
关键字定义枚举类型,以及如何声明枚举变量。 - 枚举使用:讲解如何使用枚举类型来表示一组相关的常量,提高代码的可读性和可维护性。
联合体(Unions)
- 联合体定义:介绍如何使用
union
关键字定义联合体类型,以及如何声明联合体变量。 - 联合体使用:讲解联合体的特性,即所有成员共享同一块内存空间,以及如何根据需要访问不同的成员。
数据结构基础
- 链表(Linked List):
- 单链表:介绍单链表的基本概念,包括节点的定义和链表的创建。
- 链表操作:讲解如何实现链表的插入、删除、查找等基本操作。
- 栈(Stack):
- 栈的定义:介绍栈的后进先出(LIFO)特性。
- 栈的实现:使用数组或链表实现栈,并实现栈的基本操作,如
push
、pop
、peek
等。
- 队列(Queue):
- 队列的定义:介绍队列的先进先出(FIFO)特性。
- 队列的实现:使用数组或链表实现队列,并实现队列的基本操作,如
enqueue
、dequeue
、front
等。
- 树(Tree):
- 树的定义:介绍树的基本概念,包括节点、边、根节点、叶子节点等。
- 二叉树:讲解二叉树的定义,以及如何使用结构体表示二叉树的节点。
- 二叉树遍历:介绍二叉树的三种基本遍历方法:前序遍历、中序遍历和后序遍历。
应用实例
- 结构体在实际问题中的应用:通过一些实际问题,展示如何使用结构体来组织和管理数据。
- 数据结构的应用:通过实例讲解如何使用链表、栈、队列等数据结构解决实际问题,如栈在表达式求值中的应用、队列在任务调度中的应用等。
这一章节的内容旨在帮助读者掌握结构体的使用方法,并通过结构体构建简单的数据结构,为后续更复杂的数据结构和算法学习打下基础。
教材学习中的问题和解决过程(先问 AI)
(一个模板:我看了这一段文字 (引用文字),有这个问题 (提出问题)。 我查了资料,有这些说法(引用说法),根据我的实践,我得到这些经验(描述自己的经验)。 但是我还是不太懂,我的困惑是(说明困惑)。【或者】我反对作者的观点(提出作者的观点,自己的观点,以及理由)。 )
- 问题1:结构体定义注意事项有什么?
- 问题1解决方案:在C语言中定义结构体时,需要注意以下几点:
1. 结构体名称
- 命名规范:结构体类型名称应遵循良好的命名规范,通常使用大写字母开头或全大写字母,并使用下划线分隔单词,例如
Student
或STUDENT_INFO
。 - 避免与关键字冲突:确保结构体名称不与C语言的关键字或已定义的标识符冲突。
- 描述性名称:选择能够清晰描述结构体内容和用途的名称,使代码更易读和理解。
2. 成员变量
- 类型选择:根据实际需求为成员变量选择合适的数据类型,例如使用
int
表示整数、float
或double
表示浮点数、char
数组表示字符串等。 - 成员命名:为成员变量选择有意义的名称,通常使用小写字母开头,并使用下划线分隔单词,例如
name
、age
、score
等。 - 避免重复成员:确保结构体中没有重复的成员变量,每个成员变量应具有独特的功能和用途。
- 对齐和填充:了解结构体成员的对齐和填充规则,不同编译器和平台可能有不同的对齐要求,这可能会影响结构体的内存占用和性能。
3. 结构体初始化
- 初始化方式:在定义结构体变量时,可以使用初始化列表对成员变量进行初始化,例如:
struct Student stu = {"John", 20, 85.5};
- 默认初始化:如果未显式初始化,结构体的成员变量可能会被初始化为零或随机值,具体取决于编译器和平台。
4. 结构体嵌套
- 嵌套结构体:结构体中可以嵌套其他结构体,但要注意嵌套的层次不宜过深,以保持代码的清晰和可维护性。
- 嵌套访问:访问嵌套结构体的成员时,需要使用多个
.
运算符,例如:struct Address address = {"China", "Beijing"}; struct Student stu = {"John", 20, address}; printf("%s\n", stu.address.city);
5. 结构体与指针
- 结构体指针:可以使用指针访问结构体变量,使用
->
运算符访问成员变量,例如:struct Student *p = &stu; printf("%s\n", p->name);
- 动态分配结构体:可以使用
malloc()
等函数动态分配结构体内存,但要注意内存的释放和指针的管理。
6. 结构体与函数
- 函数参数:将结构体作为函数参数传递时,可以传递结构体变量或结构体指针,根据需要选择传值或传址。
- 返回结构体:函数可以返回结构体变量,但要注意大结构体的返回可能会导致性能开销。
7. 结构体与内存管理
- 内存占用:了解结构体的内存占用情况,包括成员变量的大小和对齐填充的影响。
- 内存释放:如果结构体中包含指向动态分配内存的指针,需要在适当的时候释放这些内存,避免内存泄漏。
通过注意这些事项,可以更好地定义和使用结构体,提高程序的可读性、可维护性和性能。
- 问题2:如何实现链表的位置转换?
- 问题2解决方案:在链表中实现位置交换,通常是指交换两个节点在链表中的位置。以下是实现链表位置交换的一般步骤和注意事项:
单链表节点交换
假设我们有一个单链表,每个节点包含数据和指向下一个节点的指针。我们需要交换两个节点node1
和node2
的位置。以下是实现步骤:
1. 定义链表节点结构体
typedef struct ListNode {int data;struct ListNode *next;
} ListNode;
2. 查找节点及其前驱节点
- 首先,需要找到
node1
和node2
以及它们的前驱节点prev1
和prev2
。 - 如果
node1
或node2
是头节点,那么它们的前驱节点可以是NULL
。
3. 交换节点
- 根据
node1
和node2
的位置关系,以及它们是否相邻,分别处理不同的情况:- 如果
node1
和node2
相邻,交换它们的next
指针。 - 如果
node1
和node2
不相邻,需要调整它们的前驱节点的next
指针,以及node1
和node2
的next
指针。
- 如果
4. 处理特殊情况
- 如果
node1
或node2
是尾节点,需要特别注意尾节点的处理。 - 如果链表只有一个节点或两个节点相同,不需要进行交换。
示例代码
以下是一个简单的示例代码,展示如何交换两个节点的位置:
void swapNodes(ListNode **head, ListNode *node1, ListNode *node2) {if (node1 == node2) {return; // 相同节点,无需交换}ListNode *prev1 = NULL, *prev2 = NULL;ListNode *current = *head;// 查找node1的前驱节点while (current && current->next != node1) {prev1 = current;current = current->next;}// 查找node2的前驱节点current = *head;while (current && current->next != node2) {prev2 = current;current = current->next;}// 如果没有找到node1或node2,无法交换if (!node1 || !node2) {return;}// 处理node1和node2的前驱节点if (prev1) {prev1->next = node2;} else {*head = node2; // node1是头节点}if (prev2) {prev2->next = node1;} else {*head = node1; // node2是头节点}// 交换node1和node2的next指针ListNode *temp = node1->next;node1->next = node2->next;node2->next = temp;
}
注意事项
- 边界条件:确保处理好头节点和尾节点的特殊情况。
- 相邻节点:如果两个节点相邻,交换时要注意不要丢失链表的连接。
- 内存管理:在交换过程中,不要丢失对节点的引用,确保链表的完整性和连续性。
- 效率考虑:在实际应用中,频繁的节点交换可能会导致链表操作的效率降低,需要根据具体需求进行优化。
通过上述步骤和示例代码,可以在单链表中实现节点的位置交换。对于双向链表,交换过程类似,但需要同时调整前驱和后继指针。
- ...
基于AI的学习
问题1:举例机构体和联合体的区别:
结构体(struct
)和联合体(union
)都是C语言中用于组合多个不同类型的数据项的复合类型,但它们在内存分配和使用方式上有显著的区别。以下是结构体和联合体的区别举例:
结构体(struct
)
- 内存分配:结构体为每个成员变量分配独立的内存空间。结构体的总大小等于其所有成员变量大小的总和(考虑内存对齐)。
- 成员访问:可以同时访问结构体的所有成员变量,每个成员变量都有自己的内存地址。
- 使用场景:适用于需要存储多个相关数据项的场景,例如表示一个学生的信息(姓名、年龄、成绩等)。
结构体示例
#include <stdio.h>// 定义一个学生结构体
typedef struct {char name[50];int age;float score;
} Student;int main() {// 创建并初始化一个学生结构体变量Student stu = {"John Doe", 20, 85.5};// 访问和打印结构体成员printf("Name: %s\n", stu.name);printf("Age: %d\n", stu.age);printf("Score: %.2f\n", stu.score);return 0;
}
联合体(union
)
- 内存分配:联合体为所有成员变量分配同一块内存空间。联合体的大小等于其最大成员变量的大小。
- 成员访问:同一时间只能使用联合体的一个成员变量,因为所有成员共享同一块内存。
- 使用场景:适用于需要根据不同的情况存储不同类型的数据的场景,例如表示一个可以存储整数或浮点数的变量。
联合体示例
#include <stdio.h>// 定义一个可以存储整数或浮点数的联合体
typedef union {int intValue;float floatValue;
} Number;int main() {// 创建一个联合体变量Number num;// 存储整数num.intValue = 100;printf("Integer Value: %d\n", num.intValue);// 存储浮点数num.floatValue = 3.14;printf("Float Value: %.2f\n", num.floatValue);return 0;
}
总结
- 内存使用:结构体使用更多的内存,因为每个成员都有独立的内存空间;联合体使用较少的内存,因为所有成员共享同一块内存。
- 数据访问:结构体可以同时访问所有成员;联合体同一时间只能访问一个成员。
- 适用场景:结构体适用于存储多个相关数据项;联合体适用于根据需要存储不同类型的数据。
通过这些区别和示例,可以更好地理解结构体和联合体在C语言中的不同用途和使用方式。
问题2:如何查找链表?
在链表中查找特定的节点通常涉及遍历链表,直到找到符合条件的节点。查找操作是链表操作中的基本操作之一,以下是一些常见的查找方法和示例:
单链表查找
假设我们有一个单链表,每个节点包含数据和指向下一个节点的指针。我们需要查找包含特定值的节点。
定义链表节点结构体
typedef struct ListNode {int data;struct ListNode *next;
} ListNode;
查找特定值的节点
ListNode* findNode(ListNode *head, int value) {ListNode *current = head; // 从头节点开始遍历while (current != NULL) {if (current->data == value) {return current; // 找到节点,返回节点指针}current = current->next; // 移动到下一个节点}return NULL; // 遍历结束,未找到节点
}
双向链表查找
双向链表的查找与单链表类似,但由于每个节点都有前驱和后继指针,可以双向遍历。但通常情况下,查找操作仍然从头节点开始向后遍历。
定义双向链表节点结构体
typedef struct DoublyListNode {int data;struct DoublyListNode *prev;struct DoublyListNode *next;
} DoublyListNode;
查找特定值的节点
DoublyListNode* findNode(DoublyListNode *head, int value) {DoublyListNode *current = head;while (current != NULL) {if (current->data == value) {return current;}current = current->next;}return NULL;
}
循环链表查找
循环链表的查找也需要遍历链表,但由于链表是循环的,需要注意避免无限循环。
定义循环链表节点结构体
typedef struct CircularListNode {int data;struct CircularListNode *next;
} CircularListNode;
查找特定值的节点
CircularListNode* findNode(CircularListNode *head, int value) {if (head == NULL) {return NULL;}CircularListNode *current = head;do {if (current->data == value) {return current;}current = current->next;} while (current != head); // 循环直到回到头节点return NULL;
}
查找节点的前驱节点
在某些情况下,可能需要找到某个节点的前驱节点,例如在删除节点时。
查找特定值节点的前驱节点
ListNode* findPreviousNode(ListNode *head, int value) {if (head == NULL || head->next == NULL) {return NULL;}ListNode *current = head;while (current->next != NULL) {if (current->next->data == value) {return current; // 返回前驱节点}current = current->next;}return NULL; // 未找到
}
注意事项
- 边界条件:在查找过程中,要特别注意链表为空或只有一个节点的情况。
- 效率:查找操作的时间复杂度为O(n),其中n是链表的长度。对于大型数据集,查找效率可能较低,可以考虑使用其他数据结构(如哈希表)来提高查找效率。
- 循环链表:在循环链表中查找时,要确保不会无限循环,通常通过检查当前节点是否回到头节点来结束循环。
通过这些方法和示例,可以在不同类型的链表中实现查找操作。
三个原则:
- 切勿原封不动地接受生成式人工智能工具的输出;确保对其进行评估、完善和修改(或提示),以适应您的目标。
- 切勿将任何个人数据(自己、同学、老师等)或版权材料纳入到你的提示词中。这个可以说是保护个人隐私的最起码的举措。
- 所有人工智能生成工具都容易产生幻觉,因此会生成不准确或误导性的信息,要学会甄别信息真假
选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容
“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”
核心是要求GPT:“请你以苏格拉底的方式对我进行提问”
然后GPT就会给你提问,如果不知道问题的答案,可以反问AI:“你的理解(回答)是什么?”
如果你觉得差不多了,可以先问问GPT:“针对我XXX知识点,我理解了吗?”
GPT会给出它的判断,如果你也觉得自己想清楚了,可以最后问GPT:“我的回答结束了,请对我的回答进行评价总结”,让它帮你总结一下。
代码调试中的问题和解决过程
- 问题1:XXXXXX
- 问题1解决方案:XXXXXX
- 问题2:XXXXXX
- 问题2解决方案:XXXXXX
- ...
代码托管
(statistics.sh脚本的运行结果截图)
上周考试错题总结
- 错题1及原因,理解情况
- 错题2及原因,理解情况
- ...
其他(感悟、思考等,可选)
xxx
xxx
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 18/38 | |
第三周 | 500/1000 | 3/7 | 22/60 | |
第四周 | 300/1300 | 2/9 | 30/90 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
参考:软件工程软件的估计为什么这么难,软件工程 估计方法
-
计划学习时间:XX小时
-
实际学习时间:XX小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)
参考资料
- 《计算机科学概论(第七版)》
- ...