本文只梳理Lecture的大概提纲
注意
由于CPT102的内容大部分基于java实现数据结构的应用(Lec和Lab),这个帖子主要用来罗列知识点名字以及展示相关概念,java代码实现和具体内容还是需要与学校的PPT和老师给的JAVA代码配合观看。(其实就是我码不动字了)
每个ADT主要包含——ADT特征,ADT的部分方法,相关知识点
以下列出每个ADT的部分代表性方法,部分被继承的方法将不再重复列举
进度:完
正文:
数据结构大致分为线性(Linear)结构和层次(Hierarchical )结构
数据结构类型:Array, Stack, Queue, List, Set, Bag | Tree, Graph, Map, Network…
相关操作:增删查改排序…
- 为什么使用数据结构
- 什么是算法
- 什么是数据结构
- 数据结构是数据存储概念而非编程语言
- 静态数据结构和动态数据结构,是什么,各自的优缺点
- 评估各个ADT增删查改操作在空间,时间上的Cost
- 递归算法
- recursion和iteration的比较和相互转换
Java和算法
- Java里的抽象概念Abstraction,接口以及抽象类,Abstract Data Type抽象数据类型分别是什么,有什么不同,能否实例化instantiated
- 接口特征,抽象类特征
- 封装Encapsulation
- 方法头
- import Libraries,什么是Librariy,课程需要使用那些库util/io/swing/awt
- Collection类
- 如何创建抽象类型的实例对象
- 指明集合类型< E > → Collection type
- 迭代器 Iterator 的使用,为什么使用迭代器,
- List 和 array的比较,ArrayList是什么
- 异常Exception是什么,为什么要抛出异常,捕获异常
- 异常何时抛出,如何抛出异常
- 如何处理异常(RuntimeException和Other Exception不同的处理策略),getMessage()方法是什么
- 指针,地址空间及垃圾回收
- 黑箱测试,白箱测试(Lec12)
- 二分法搜索(Lec16)分治思想
- 给定T(n) 算O(n)
- 基本排序算法 (Lec17)按照效率,空间,数据要求评估不同排序算法
- 快速排序,选择排序,归并排序
- 递归实现排序算法
Iterator
迭代器,所有Collection类都可以使用迭代器
· hasNext(): 返回boolean,指针之后是否有元素
· next(): 返回指针之后的下一个元素,移动指针往后移动1个元素
· remove(): 删除上次迭代的元素(这个方法不怎么使用,但是必须要声明)
- 区分Iterable接口 和 Iterator接口(Lec05)
Comparable
比较器,所有Collection类都可以使用比较器
· compareTo(T ob): Comparable的接口的方法,所有继承自Comparable的对象都要实现该方法,方法代表了natural order,根据传入对象与自己的比较返回整数,自己大返回1,对面大返回-1,平手返回0
· compare(Object,Object): Comparator接口的方法,比较两个对象,<返回-1, =返回0, >返回1
- natural ordering是什么
- 区分Comparable 和 comparator
- Collections.sort(…, Comparator) 的使用
Collection
这里讨论java中的接口,所有其他ADT都继承于Collection
· isEmpty(): 返回是否为空
· size(): 返回已包含元素的数量
· contains(E elem): 返回是否包含某个元素
· add(E elem): 在尾部添加一个对象作为元素,返回操作状态
· remove(E elem): 移除一个元素,返回操作状态
· iterator():返回一个迭代器
· clear(): 利用迭代器清空集合
· addall(Collection): 合并两Collection
· removeAll(Collection): 移除所有位于两Collection交集里的所有元素
· containsAll(Collection): 返回是否包含这个Collection的所有元素
List
继承自Collection
List特性:没有访问限制(随机访问),允许重复
· add(index, item): 在下标处添加元素,该位置以及之后的元素后移一位,返回操作状态
· remove(index):移除下标处元素,该位置之后的元素前移一位,返回操作状态
· get(index): 返回某个元素值下标
· set(index, item): 将下标处元素替换,返回操作状态
· indexOf(item): 返回某个元素下标
· subList(int from, int to): 返回子List
AbstractList
继承自List
声明了size();get(index);等方法
定义了isEmpty();add();contains();clear()等方法
Array
特点:数组内元素有顺序,随机访问,数组长度不可变,允许重复
Bag
继承自List
Bag特性: 其内元素没有顺序,没有访问限制(随机访问),允许重复
· add(value): 添加元素,返回操作状态
· remove(value): 移除元素,返回操作状态
· contains(value): 返回是否包含该元素
· findElement(value): 返回匹配的元素
- 什么时候使用Bag
Set
继承自List
Set特性:其内元素没有顺序,没有访问限制(随机访问),排除重复项
· add(value): 添加元素,返回操作状态,元素重复则False
· remove(value): 移除元素,返回操作状态
· contains(value): 返回是否包含该元素
· findElement(value): 返回匹配的元素
· clear(): 清空
Stack
继承于List
Stack特性:其内元素有顺序,先进后出,后进先出,顺序访问,不排除重复项
· push(value): 将对象元素入栈,放置栈顶
· pop(): 出栈一个元素,从栈顶移除
· peel(): 不弹出栈顶元素,返回该栈顶元素
- Stack在HTML中的使用
- Stack作为栈存储程序各方法的状态
- Stack在递归中的使用
- 利用Stack判断代数表达式是否括号对称
- 利用Stack处理前缀Polish,中缀Infix,后缀表达式Postfix之间的转换(lec 04)
- 利用Stack对字符逆序操作
Map
继承自List
Map特性:其内元素无顺序,无访问限制(随机访问),key不能重复,每个元素存储为(key, value)的形式。
· get(key): 返回该key对应的val
· put(key, value): 重新设定key对应的val
· remove(key): 移除key为指定key的元素
· containsKey(key)返回是否包含key为指定key的元素
· keySet(): 返回keys的Set对象
· values(): 返回vals的Collection对象
· entrySet(): 返回所有元素的Set对象
- 使用Map计算文档中单词使用频率(Lec05)
- 通过key,val,pair分别迭代Map类所有元素
- 使用Map表示cast表
Queue
继承自List
Queue特性:其内元素有顺序,删除操作只能在一端进行,不排除重复项
· offer(value): 添加元素进队列入端,返回操作状态,也叫做enqueue
· poll(): 移除并返回出端的一个元素,也叫做dequeue
· peek(): 不移除地返回出端元素
· remove(): 移除并返回出端的元素,当队列为空时抛出异常
· element(): 非移除地返回出端元素,当队列为空时抛出异常
- 哈夫曼编码Huffman coding的优先级队列应用
- Priority Queue是什么,如何用数组实现
- 使用count的queue
- 使用front和back指针的循环状queue
- 上面两者的差别
ArrayList
继承自List的类
特征:相比于数组,ArrayList可以自动扩容。
· size()
· get(index)
· set(index,value)
· remove(index):之后的元素需要前移
· add(index,value):之后的元素需要后移
· iterator()
- count这个变量的作用
- 哪些方法会涉及到扩容
- 如何扩容
- remove()方法移除元素后,之后的元素如何变动(删除原ArrayList最后一位)(Lec08)
- add()方法添加元素后,之后的元素如何变动 (是否扩容)(Lec08)
- 实现迭代器
- 实现迭代器的remove方法
- remove和next方法中canRemove变量的作用
- 多迭代器冲突
10.扩容带来的时间复杂度不同
ArraySet
特征:其内元素无顺序,可以实现自动扩容,随机访问,排除重复
· contains(item):返回是否包含某元素
· add(item) :通常在尾部加入,应避免重复
· remove(item) :定位并移除指定元素,与arraylist不同的是无需将之后的元素都前移而是只把最后一位元素挪进空位
- contains的复杂度为n
SortedArraySet
特征:与ArraySet类似,只是元素在存储时按照排序存储,因此定位元素时可以二分查找,加快查找速度。
- contains的复杂度为logn
- Set,ArraySet,SortedArraySet之间的比较
- 为何ArraySet,SortedArraySet在频繁add和remove时效率差不多
Linked Node(val, nextnode):
节点类,串起来可表示链表
value记录值,next记录指针
· setNext(): 设立指针指向下一个节点
使用串联起来的LinkedNode已经可以实现链表的操作了,但是把各种操作封装起来更好一些,如下面的LinkedList
Linked List
继承于AbstractList的链表类,其内有Node私有类表示节点
特性:其内元素有顺序,每个节点会记录下一个节点的地址,形成链表,访问时必须顺序访问,元素可重复
· get(index): 返回节点值
· set(index, item): 设立节点值
· add(index, item): 添加新元素
· remove(item):删除某一元素
· remove(index): 删除下标处元素
- 头指针
- 修改或添加元素时的双指针遍历或.next.next提前遍历的原因
- 使用图像表示链表
- 使用循环创建链表
- 使用循环输出链表
- 插入删除操作(lec 13-14)
Linked Stack
特性:由链表存储的栈结构,头节点方向代表栈顶
· push(item): 元素入栈,头节点指向新元素,新元素指向原第一位元素
· pop(): 元素出栈,头节点指向原第二位元素
· peek(): 非弹出返回栈顶元素
· size(): 返回链表长度
- 头节点
- 为什么头节点方向代表栈顶,与链表尾部代表栈顶有何差别
Linked Queue
特性:由链表存储的队列结构
链表头节点可以作为队列入端,也可以作为出端,相应地,链表尾节点可以作为出端或者入端。更高效的做法是改变下链表头节点,使头节点有两指针分别指向队列入端元素和队列出端元素(学校PPT做法是头指针指向队列出端,尾指针指向队列入端)
· offer(value): 添加元素进队列入端,返回操作状态,也叫做enqueue
· poll(): 移除并返回出端的一个元素,也叫做dequeue
· peek(): 不移除地返回出端元素
·
Tables(Maps)
类似于Maps,只是一个key后面跟着许多values
· insert(key, item): 在某个key中插入val
· lookup(key): 返回key及其values
· remove(key): 移除key及其values
- 由链表实现Tables
- 由二叉树实现Tables
- 还可以由哈希表实现
Hash Tables
增删查时间复杂度为O(1),存在一个长为N的数组,定义一个哈希函数(Hash function), 输入任意元素值,函数将该值映射为hash值,代表表中某一位置。对于同一输入得出的哈希值是一样的。
- 哈希table的大小如何影响空间和时间效率
- 哈希值为什么需要定长
- 地址范围为0到容量-1
- 好的哈希函数应该:避免冲突;均匀分散元素;计算复杂度不能太高
- 字母哈希时需要注意ASCII表是从0101到0172
- 数字哈希Mid-square method(Lec23)
- 字符串哈希(4-byte看成int型,累加)Lec23
- 处理哈希值冲突
- 处理满哈希表
Tree
树由节点构成,二叉树的一个节点下可划分为左子树和右子树,节点内有key值,左指针和右指针。
- 哈夫曼编码Huffman coding的二叉树应用
- 树与线性存储结构的差别,树的优点,树的应用
- 平衡二叉树AVL是什么
- 递归树型结构Recursion tree表示递归
- 二叉树的前序遍历pre,中序遍历in,后序遍历post以及转换前中后缀表达式
- 使用队列queue实现树的层序遍历
- In general, 节点的子节点之间无先后之分(Binary tree has no ordering upon its sibling nodes)。但是各种应用中,也有规定子节点先后顺序的树。
BinaryTree
java实现二叉树,特点:一个节点可以有多个子节点,使用两个BinaryTree记录左右子节点
· getValue()
· getLeft(): 返回左孩子节点
· getRight(): 返回右孩子节点
· setValue()
· setLeft(tree): 设置左子树
· setRight(tree): 设置右子树
· isLeaf()
· find(val): 返回值为val的节点
- 使用java构造二叉树
- java递归前序遍历二叉树
General Tree
java实现普通树,特点:一个节点可以有多个子节点,节点记录的子节点含有顺序,使用List记录所有children
· getChildren():返回所有孩子节点
· getChild(i): 返回第i个孩子节点
· addChild(child): 往List里添加一个节点
· addChild(i,child): 在List第i个位置添加一个节点
- 使用java构造普通树
- java递归前序遍历普通树
Binary Search Trees
二叉搜索树特征:每个节点的左孩子节点值<该节点值<该节点右孩子节点值
增:从根节点开始,大于当前向左下移动,小于当前向右移动,直到底部
删:删除某一节点,将右子树的最大值填补进空缺。
- 增删查的平均时间复杂度为O(log N),最坏O(N)
- BST什么情况时间复杂度最差→退化成链表degenerative cases
Balanced Search Trees
平衡搜索树特点:每个节点的左孩子节点值<该节点值<该节点右孩子节点值且任意节点的左子树深度和右子树深度相差≤1
- 增删查的最坏时间复杂度为O(log N)
- 什么是AVL Trees(自平衡二叉搜索树)
- 为什么需要旋转操作
- 旋转rotation操作的实现(Lec21)
- 插入元素后的AVL自平衡操作
Graph
特点:由点V和边E组成,
-
点与点的邻接adjacent以及点与边的关联incident
-
simple graph简单图点点间只连一线且没有loop
-
度序列非负非升序
-
加权图weighted graph
-
有向图digraph,出度入度
-
subgraphs和点集相同的特殊子图:spanning subgraph
-
邻接矩阵adjacency和关联矩阵incidence
-
walk点到点路径,trail点到点的路径且边不重复,path点到点的路径且边和点都不重复
-
连通与非连通
-
Tree是没有回环的连通图
- 图的生成树,最小生成树
- 贪婪算法生成最小生成树(Lec26)
- 求两节点间最短路径(Lec27)(Dijkstra’s algorithm)
一些补充:
Lec04(前中后缀表达式转换,单栈single,双栈dual):
前缀profix:操作符在前,+ab
中缀infix:操作符在中,a+b
后缀postfix:操作符在后,ab+,主要是后缀
操作符优先级: 配对半括号 > ^ > × / > + - >首次出现的半括号
中缀转后缀:
从左到右扫描中缀表达式,维护操作符栈
-
遇到操作数, 直接输出
-
遇到操作符后, 如果操作符堆栈为空, 则直接压入操作符,
如果操作符堆栈非空,判断当前操作符与栈顶操作符的优先关系, 假如栈顶操作符的优先级≥当前操作符的优先级, 那么弹出栈顶操作符直到栈顶操作符优先级<当前操作符优先级. 最后将当前操作符入栈 -
如果遇到左括号,直接入栈
-
如果遇到右括号, 那么将栈顶操作符弹出, 持续弹出直到遇到匹配的左括号, 左括号弹出但不输出
-
表达式读入完毕, 若栈不为空, 则持续弹出栈顶操作符, 直到栈为空
中缀转前缀:
从右到左扫描中缀表达式,维护操作符栈
-
遇到操作数, 直接输出
-
遇到操作符后, 如果操作符堆栈为空, 则直接压入操作符,
如果操作符堆栈非空,判断当前操作符与栈顶操作符的优先关系, 假如栈顶操作符的优先级>当前操作符的优先级, 那么弹出栈顶操作符直到栈顶操作符优先级≤当前操作符优先级. 最后将当前操作符入栈 -
如果遇到右括号,直接入栈
-
如果遇到左括号, 那么将栈顶操作符弹出, 持续弹出直到遇到匹配的左括号, 左括号弹出但不输出
-
表达式读入完毕, 若栈不为空, 则持续弹出栈顶操作符, 直到栈为空
-
反转输出字符串
计算evaluate后缀表达式postfix:
从左到右扫描后缀表达式,维护操作数栈
- 扫描到数字,入栈
- 扫描到操作符,依次出栈两数字,先出栈的作为操作符后数字,后出栈的作为操作符前数字,计算结果并把数字入栈
计算evaluate前缀表达式profix:
从右到左扫描后缀表达式,维护操作数栈
- 扫描到数字,入栈
- 扫描到操作符,依次出栈两数字,先出栈的作为操作符前数字,后出栈的作为操作符后数字,计算结果并把数字入栈
用双栈计算evaluate中缀表达式infix
维护操作符栈和操作数栈,从左到右扫描中缀表达式。
- 扫描到数字,入操作数栈
- 扫描到操作符,按照中缀转后缀表达式的规则压入操作符栈
- 如果上一步pop出来了操作符,那么对于被pop出来的操作符,依次pop操作数,数字从后向前交叉操作符,计算结果再入栈
- 如果中缀表达式扫描结束后,操作符栈非空,继续按照以上规则pop操作符计算
Lec06(迭代器,比较器):
继承自Iterator的类是个迭代器,其作用是迭代该迭代器属于的对象内元素,需要实现next()和hasNext(), remove()方法
Iterable是可迭代声明,继承自Iterable的类可以迭代,该类应该实现一个叫 iterator() 的公开方法,这个方法会返回一个迭代此类的迭代器,属于该类的迭代器的类代码位于该类的内部,并且是私有的。
继承自Comparator的类是个比较器,其内需要实现compare(E a, E b)方法,该方法作用是比较传入的a, b对象。
Comparable是可比较对象声明,继承自Comparable的类可以被比较以及排序,该类应该直接实现一个叫compareTo(Object)的方法,该方法将这个类对象与传入对象比较。compareTo()定义的比较方式代表了该类的自然顺序,如果默认调用Collection.sort()的话会按照自然顺序进行排序。当然也可以创建一个比较器,然后将比较器传入sort(),sort()就会按照比较器规定的比较方式进行排序。
Lec13,14(对链表的删除操作的实现步骤):
Leetcode-删除链表的节点
假设链表头节点指针为data,链表长度记录为count删除成功返回True,无需删除或出问题返回False
遍历链表删除节点:
- 如果想要删除的元素为null或链表无链表头节点则返回False
- 如果头节点与预删除元素值相同,将头节点指针指向next,链表长度count-=1,返回True
- 否则,链表往后查找与预删除元素值相同的节点,(实际遍历的是与预删除元素值相同的节点的前一个节点):
- 创建一个临时的链表头节点指针node
2.1. 如果node指向的当前节点有后续节点以及下个节点值不等于预删除值,循环node=node.next - 退出循环时如果为尾节点,返回False
- 退出循环时如果是中间节点,代表后续节点既是目标节点,将node.next更新为node.next.next,删除目标节点,count-=1,返回True
- 创建一个临时的链表头节点指针node
Lec16 (给定T(n) 算O(n) ):
题干:
解题: 根据T(n)递推公式,
T(n)=2T(n/2)+n ········等号右边的式子根据Guess的式子(括号里变成n/2),放缩至
T(n)≤nlog(n/2)+n ········再把log括号里的除二提出来
T(n)≤n(logn-log2)+n ········因为log2=1
T(n)≤nlogn-n+n ········加n减n相消,得证