Skip to content

zhuiguang49/Data-structures-and-algorithms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

数据结构与算法 2024秋 课程仓库

Lab 1

hello目录下编写源文件hello.cpp,Makefile,make后可得到可执行文件hello,运行后显示"Hello World!"。

Lab 2 (Chicken)

  1. 深度拷贝与连续赋值:
  • 复制操作: 在拷贝对象时,为name动态分配新的内存,并将源对象的name内容复制到新对象中,确保两个对象拥有独立的内存。

  • 赋值操作符重载: 重载operator = ,在赋值时进行深拷贝,返回*this,支持了连续赋值。且每个对象独立地管理自己的内存,避免指针共享导致的潜在问题。

  1. 内存管理
  • setName()和赋值运算符中检查并释放旧的name内存,避免内存泄漏,通过delete[]释放动态分配的内存,使得对象析构时不会产生内存泄漏。
  • 在赋值运算符中,检查this != &other,避免自我赋值导致错误的内存释放。
  1. 左值引用、指针和const关键字
  • 使用const关键字保护getNamegetAge,保证这些函数不会被修改对象成员,并且在传递对象时使用const引用。
  1. valgrind检查内存泄漏: 截图如下

无内存泄漏

Lab 3 Linkedlist

  1. getCurrentVal()
  • currentPos不为nullptr时返回当前节点的值,如果currentPosnullptr,报错Empty current position! Can't get value!
  1. setCurrentVal(T &_val)
  • 确保currentPos不为nullptr时允许修改数据,如若为nullptr则报错Empty current position! Can't setvalue!
  1. isEmpty()
  • 修改了老妖的拼写错误(手动狗头)。
  • 检查链表是否为空,返回true表示链表为空,false表示链表不为空。
  1. insert(T _val)
  • 如果currentPosnullptr,表示链表为空,将元素插入为新的头结点,并更新currentPos指向新插入的节点;若currentPos不为空,则在其后插入新节点,并更新currentPos
  • 插入后,链表的大小增加。
  1. remove()

remove()函数原先删除的是currentPos后面的元素而非currentPos指向的当前元素,这不符合实际工作的需求,我们将其改为删除currentPos指向的元素本身

  • 如若链表为空或currentPos为空,则不进行任何操作。
  • currentPos是链表的头结点,删除头结点并更新headcurrentPos
  • 如若currentPos不是链表的头结点,删除该节点并更新currentPos为其后的节点。
  • 删除后,链表的大小减小

修改了remove()函数后的输出:

无内存泄漏

Lab4 List

  1. List.h
  • List.h 中,添加了迭代器后向遍历--)的实现,使得List支持使用迭代器进行双向遍历。
  1. List.cpp
    List.cpp中,我们编写了测试程序,覆盖以下操作验证List类的正确性
  • 元素插入(push_backpush_front
  • 元素删除(pop_backpop_fronterase
  • 前向和后向迭代器遍历
  • 拷贝构造和移动构造
  • 拷贝赋值和移动赋值
  • 链表的清空操作
  1. 无内存泄漏:
    我们使用Valgrind工具检测确保程序无内存泄漏,截图如下: 无内存泄漏

Lab5 BST_remove

  1. BinarySearchTree.h的修改

    我们优化了 BinarySearchTree 类中的 remove 函数,避免递归删除过程中不必要的节点值复制操作。为此,我们新增了一个辅助函数 detachMin,用于从右子树中找到并移除最小节点。这样在删除有两个子节点的节点时,可以直接使用 detachMin 返回的节点进行替换,从而提高删除操作的效率。

  2. main.cpp的测试

    main.cpp 中,我们编写了多种测试用例,验证 remove 函数在以下场景中的正确性:

    • 删除不存在的节点,确保树结构不变。
    • 删除叶子节点,确保其成功移除且不影响其他节点。
    • 删除只有一个子节点的节点,验证树的结构更新正确。
    • 删除有两个子节点的节点,确保 remove 函数能正确替换节点。
    • 删除根节点,包括根节点有多个子节点的情况。
    • 重复删除同一节点,测试函数是 我们编写了一个 Makefile,提供了以下两种操作:
    • make run:编译 main.cpp 并运行程序,输出测试结果。
    • make report:使用 xelatex 编译实验报告 report.tex,生成 report.pdf 文件。

    此外,可以使用 make clean 清理临时文件,或使用 make distclean 完全清理生成的文件。

Lab6 AVLTree_remove

实现方案

本次实现主要围绕AVL树的平衡维护,核心在于正确处理删除操作后的再平衡:

  1. 节点存储结构
struct BinaryNode {
    Comparable element;
    BinaryNode *left;
    BinaryNode *right;
    int height;  // 新增高度字段
};
  1. 高度维护
// 获取节点高度
int height(BinaryNode *t) const {
    return t == nullptr ? 0 : t->height;
}

// 更新节点高度
void updateHeight(BinaryNode *t) {
    if (t != nullptr) {
        t->height = std::max(height(t->left), height(t->right)) + 1;
    }
}
  1. AVL树的删除操作
  • 先按二叉搜索树的方式删除节点
  • 删除后自底向上更新节点高度
  • 检查平衡因子进行必要的旋转
  • 通过递归返回保持树的平衡性
  1. 平衡维护
int getBalance(BinaryNode *t) const {
    return t == nullptr ? 0 : height(t->left) - height(t->right);
}

Makefile使用说明

基本命令

make        # 编译程序
make run    # 运行程序
make clean  # 清理编译文件,保留PDF
make report # 生成PDF报告
make time   # 测试运行时间

可能会遇到栈溢出的问题,使用前建议设置 ulimit -s unlimited,该命令只对当前shell有效

About

Lab of Data structures and algorithms in ZJU

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published