类库与数据结构课程复习要点
Ch1: 数据结构与编程基础
-
数据结构相关的基本概念
数据结构是一种组织、管理和存储数据的方式,使得数据可以高效地访问和修改。基本数据结构包括数组、链表、栈、队列、树、图等。理解数据结构的基本概念是进一步学习算法和程序设计的基础。 -
面向对象的基本概念和原则
面向对象编程(OOP)是一种编程范式,它通过封装、继承和多态等特性,将数据和操作封装在对象中,使得代码更易于维护和扩展。OOP的主要原则包括:- 封装:将数据和操作封装在类中,隐藏内部细节。
- 继承:允许子类继承父类的属性和方法。
- 多态:通过接口或抽象类,实现不同子类的相同操作。
-
开闭原则(The Open-Closed Principle)
开闭原则是OOP的设计原则之一,指的是软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。即系统应该通过扩展实现新功能,而不需要修改已有的代码,从而降低维护成本。 -
子类替换原则(Subclass Substitution Rule)
子类替换原则(Liskov替换原则)是OOP的一个重要原则,指的是程序中的对象可以被其子类实例替换,而不会影响程序的正确性。即子类必须能够替代父类的行为而不会引入错误。 -
编程基础(C++)
C++是一种面向对象的编程语言,提供了丰富的语法和标准库支持,适用于系统级和应用级开发。在数据结构课程中,C++的指针、引用、类和模板等特性为实现复杂的数据结构提供了基础。
Ch2: 容器与数据结构
-
容器的基本概念
容器是用于存储和组织数据的结构,STL提供了多种容器类型(如vector、list、deque、set、map等),用于不同的数据存储需求。容器提供了便捷的接口来操作和访问存储的数据。 -
基于连续结构(array)和链接结构(linked-list)实现基本容器的原理
- 数组(Array):在内存中是连续分布的,支持高效的随机访问,但不适合频繁插入和删除操作。
- 链表(Linked List):由一系列节点构成,每个节点包含数据和指向下一个节点的指针。链表适合频繁插入和删除操作,但不支持随机访问。
-
迭代器的概念与实现
迭代器是一种设计模式,用于在不暴露底层数据结构的前提下遍历容器。STL中的迭代器类似于指针,可以通过递增操作移动到下一个元素。不同容器提供不同类型的迭代器,例如随机访问迭代器、双向迭代器等。
Ch3: 算法复杂度
-
算法时间复杂度的概念
时间复杂度是衡量算法执行时间随输入规模增长而增长的速度。常见的时间复杂度有常数时间O(1)、线性时间O(n)、对数时间O(log n)等,帮助我们分析算法的效率。 -
代码段和常见算法时间复杂度的计算
通过分析代码结构(如循环嵌套和递归调用),可以计算出算法的时间复杂度。例如,一个嵌套循环的时间复杂度通常是O(n^2),递归算法的时间复杂度可以通过递归树或主定理来计算。
Ch4: 递归
-
递归的基本概念、递归函数的基本形式和执行过程
递归是一种在函数中调用自身的编程方法。递归函数通常包含一个基准条件(终止条件)和递归步骤。递归的执行过程是自顶向下调用,自底向上返回。 -
简单递归算法的编程实现
递归常用于解决分治问题,如斐波那契数列、阶乘计算、二叉树遍历等。例如,阶乘的递归实现通过n! = n * (n-1)!来递归调用自身。 -
递归的时间复杂度
递归算法的时间复杂度可以通过递归关系式来计算,通常使用递归树或主定理来分析。例如,斐波那契数列的递归时间复杂度为O(2^n)。
Ch5: Vector 和 Deque
-
Vector 和 Deque 的定义和实现原理(逻辑结构和存储结构)
- Vector:动态数组,支持随机访问,能够根据需求自动扩容。vector使用连续的内存空间,适合读取和末尾插入操作。
- Deque:双端队列,支持在头尾插入和删除操作,适合频繁的头尾数据操作。
-
Vector 和 Deque 容器类的使用
- 声明对象:使用
vector<int> v;
或deque<int> d;
来声明vector和deque对象。 - 调用方法:
push_back
用于末尾添加元素,pop_back
用于移除末尾元素,deque还支持push_front
和pop_front
。 - 储存元素
- push_back:在容器末尾添加元素。
- insert:在指定位置插入元素。
- emplace_back:在容器末尾原地构造元素(避免额外的拷贝),效率更高。
- assign:将容器替换为指定数量的某个值或从其他范围赋值。
- 声明对象:使用
-
使用 Vector 和 Deque 实现特定的算法
Vector和Deque常用于实现队列、栈等数据结构。例如,用Vector实现栈,用Deque实现双端队列。
Ch6: List
-
List 的定义和实现原理(逻辑结构和存储结构)
List是一种双向链表结构,每个节点包含数据和指向前后节点的指针。List适合频繁插入和删除操作,但不支持随机访问。 -
List 容器类的使用
- 声明对象:
list<int> lst;
- 调用方法:使用
push_back
和push_front
插入元素,pop_back
和pop_front
删除元素,还支持insert
和erase
操作。
- 声明对象:
-
使用 List 实现特定的算法
List常用于需要频繁插入和删除操作的算法,例如LRU缓存淘汰算法。
Ch7: 容器适配器
-
容器适配器的概念和实现原理
容器适配器是对容器的封装,提供特定的接口,如stack、queue和priority_queue。适配器底层使用其他容器(如deque或vector)实现。 -
Queue 和 Stack 的定义和实现原理
- Queue:先进先出(FIFO)结构,只能从队尾插入,从队首移除。
- Stack:后进先出(LIFO)结构,只能从栈顶插入和移除元素。
-
Queue 和 Stack 的使用
Queue和Stack在算法中的应用广泛,如广度优先搜索(BFS)和表达式求值。 -
应用:使用 Queue 和 Stack 实现特定算法
- 队列:实现排队系统。
- 栈:用于表达式转换(中缀转后缀、前缀),递归算法的非递归实现。
-
应用容器适配器思想改造已有容器
容器适配器通过限制操作方式改造容器,确保数据按特定方式存取,如只允许头部或尾部的操作。
Ch8: 二叉树
-
二叉树的基本概念
二叉树是一种每个节点最多有两个子节点的数据结构,常用于实现树形结构。 -
二叉树常见操作的递归实现
递归用于计算节点数、叶子数、树的高度等操作。 -
不同类型树的特性
- 普通树:
- 每个节点可以有任意数量的子节点。
- 没有平衡性或有序性限制。
- 二叉树(Binary Tree)
- 每个节点最多有两个子节点:左子节点和右子节点。
- 特性:节点度最多为2。子树通常分为左子树和右子树。
- 完全二叉树(Complete Binary Tree)
- 除最后一层外,每一层的节点都已满。
- 最后一层的节点从左到右连续排列。
- 满二叉树(Full Binary Tree)
- 每个非叶子节点都有两个子节点。
- 平衡二叉树(Balanced Binary Tree)
- 左右子树的高度差不超过某个常数(通常为1或log(n))。
- 二叉搜索树(Binary Search Tree, BST)
- 特性:
- 左子树中所有节点的值小于根节点的值。
- 右子树中所有节点的值大于根节点的值。
遍历性质:中序遍历可以得到递增序列。
- AVL树
- 每个节点的左右子树高度差(平衡因子)绝对值不超过1。
- 红黑树(Red-Black Tree)
- 一种平衡二叉树,但平衡条件比AVL树宽松。
- 特性:
- 每个节点要么是红色,要么是黑色。
- 根节点为黑色。
- 红色节点的子节点必须是黑色(没有两个连续的红色节点)。
- 从任意节点到其所有叶子节点的路径中,黑色节点数量相同。
-
二叉树遍历及实现
二叉树遍历方式包括前序、中序、后序和广度优先遍历。 -
二叉搜索树(BST)概念和实现
BST是一种有序树,左子树小于根节点,右子树大于根节点,常用于查找操作。 -
BST的查找、插入、删除算法
在BST中,查找、插入和删除操作的时间复杂度为O(log n)。
Ch9:
平衡二叉树
-
平衡二叉树的概念
平衡二叉树保证任意节点左右子树的高度差不超过1,以提高查找效率。 -
AVL树的基本概念
AVL树是一种严格平衡的二叉搜索树,通过旋转操作保持平衡。 -
二叉树的四种旋转操作
左旋、右旋、左右旋和右左旋用于调整AVL树的平衡。
Ch10: 红黑树
-
红黑树的基本概念
红黑树是一种平衡二叉树,具有红黑节点的限制,确保树的高度近似平衡。 -
红黑树的查找、插入、删除操作
红黑树的插入和删除需要通过颜色调整和旋转操作来保持平衡。 -
基于红黑树的容器类
红黑树支持map、set等关联容器,便于高效查找和排序。 -
map和set容器的声明和使用
使用红黑树实现的map和set支持高效的键值查找和排序。
Ch11: 优先级队列
-
优先级队列的概念
优先级队列是一种按照优先级存储元素的数据结构,通常基于堆实现。 -
堆的概念
堆是一种完全二叉树,分为最大堆和最小堆,支持高效的插入和删除操作。 -
堆的插入、删除操作过程
堆的插入操作是将新元素加入末尾,再上浮至合适位置;删除操作通常移除根节点后重建堆。
Ch13: 哈希
-
哈希的概念和作用
哈希是一种通过哈希函数将数据映射到特定位置的技术,用于高效的数据存取。 -
哈希函数的面向对象实现
可以将哈希函数封装为类,实现灵活的哈希处理。 -
哈希冲突处理机制
- 链式哈希:用链表处理冲突。链式哈希(也称为分离链接法)在每个哈希表的槽位(桶)中使用一个链表来存储映射到相同哈希值的多个元素。当哈希冲突发生时,冲突的元素会被追加到该槽位的链表中。
- 开放地址法:使用线性探测、二次探测或双哈希处理冲突。开放地址法不使用链表,而是将冲突的元素存储到哈希表的其他空闲位置。每当发生哈希冲突时,算法会根据一定的探测(probing)规则寻找下一个空位来存储冲突的元素。