数据结构与算法分析-笔记


参考书籍:[1]Clifford A.Shaffer.数据结构与算法分析[M].北京:电子工业出版社,2020.

Chapter 1 Data Structures and Algorithms

1.4 Problems, Alogorithms, and Programs

Q:What can be called an algorithm?
1.It must be correct.
2.It is composed of a series of concrete steps.
3.It is no ambiguity.
4.It must be composed of a finite number of steps.
5.It must terminate.

Chapter 2 Mathematical Preliminaries

2.3 Logarithms 对数

log ⁡ 2 x = y \log_2 x=y log2x=y,则2可省略: log ⁡ x = y \log x=y logx=y

Chapter 3 Algorithm Analysis*

Asymptotic analysis attempts to estimate the resource consumption of an algorithm.

3.1 Introduction

growth rate
2 < log ⁡ 2 x \log_2 x log2x < n 2 / 3 n^{2/3} n2/3 < n < n 2 n^2 n2 < 3 n 3^n 3n < n!

3.4 Asymptotic Analysis 渐近分析

Upper Bounds 上限: O ( g ( n ) ) O\left(g(n)\right) O(g(n))
Lower Bounds 下限: Ω ( g ( n ) ) \varOmega \left(g(n) \right) Ω(g(n))
当上限下限一样时用: Θ ( g ( n ) ) \varTheta \left(g(n) \right) Θ(g(n))

Simplifying Rules 化简法则
1.省略常系数: Θ ( k g ( n ) ) = Θ ( g ( n ) ) \varTheta \left(kg(n) \right)=\varTheta \left(g(n) \right) Θ(kg(n))=Θ(g(n))
2.取最高次项: Θ ( g ( n ) + f ( n ) ) = Θ ( max ⁡ ( g ( n ) , f ( n ) ) ) \varTheta \left(g(n)+f(n) \right)=\varTheta \left(\max (g(n),f(n)) \right) Θ(g(n)+f(n))=Θ(max(g(n),f(n)))

3.5 Calculating the Running Time for a Program

1.sum = 0; 赋值: Θ ( 1 ) \varTheta \left(1 \right) Θ(1)
2.for (i=1;i<=n;i++) { sum += n;}循环: Θ ( n ) \varTheta \left(n \right) Θ(n)
3.

for(i=1;i<=n;i*=2)
	for(j=1;j<=n;j++)
		sum++;

多重循环(内外层相乘): Θ ( n log ⁡ n ) \varTheta \left(n\log n \right) Θ(nlogn)

Chapter 4 Lists, Stacks and Queues

4.1 Lists 线性表

线性表存在唯一的 head 和 tail ,数据有次序。
<20, 23 | 12, 15> : current element is 12, current position is 2.

4.1.1 Array-based Lists 顺序表:所有数据依次排列储存

图例Insert 插入数据

for(int i=listSize; i>curr; i--)
	listArray[i] = listArray[i-1];

将数据后移来留出空间, Θ ( n ) \varTheta \left(n \right) Θ(n)
Performance of Array-based lists
Θ ( n ) \varTheta \left(n \right) Θ(n):Insert, delete (remove) and locate
Θ ( 1 ) \varTheta \left(1 \right) Θ(1):clear, empty, full, length, replace, get, prev(当前位置向前一步)

4.1.2 Linked Lists 链表:数据可以不连续储存,可以扩充

图例链表由结点(Node)组成,Node = element + next (元素和指针)

Singly Linked List 单链表
带表头结点,位于表的最前端,不储存数据,可以简化链表操作。
tip:在 curr 处插入元素不等于在 i 处插入(前者直接插入,后者需要从头查找 i 的位置)
在链表第 i 个结点插入新元素 x

if(head == NULL || i==0){ //插在表前
	newnode -> next = head;
	if(head == NULL) tail = newnode; //原来为空表
	head = newnode;}      //转移表头
else{                     //插在表中或末尾
	newnode -> next = p -> next;
	if(p -> next == NULL) tail = newnode;
	p -> next = newnode;} //更改了两个指针的指向,使新节点插入

Performance of Singly Linked List
Θ ( 1 ) \varTheta \left(1 \right) Θ(1):Insert, delete (remove)
Θ ( n ) \varTheta \left(n \right) Θ(n):prev(当前位置向前一步), direct access

Space Comparison
n:列表中元素的数量
E:每个数据占据的空间
P:每个指针占据的空间
D:列表中最多可有元素数量
DE<n(P+E)时,Singly Linked List 比 Array-based Lists储存效率更低。

Circular List 循环列表
循环列表最后一个结点的next指针指向表的前端
图例图例
Doubly Linked Lists 双向列表
相比单向列表增加了向前的指针,解决了单向列表不方便向前移动查找的缺点。但更多的指针意味着需要更多的储存空间来存放指针。

4.2 Stacks 栈

先进后出(LIFO)的线性表 (包括线性表和链表) ,栈的顶部在线性表的尾部(即 push 和 pop 同等与线性表在尾部 insert 和 remove)。
入栈PUSH:(如果装多了会overflow溢出)
图例
出栈POP:(如果取多了会underflow下溢)
图例Stack Application
函数的嵌套,递归等

4.3 Queues 队列

先进先出(FIFO)的线性表,头部front,尾部rear。
图例Empty queue: rear == front
Full queue: (rear+1)%maxSize==front

Chapter 5 Binary Tree

5.1 Definition 定义

node 结点
subtree 子树,左右子树不同 degree 结点的子树数,二叉数 ⩽ \leqslant 2
children 子结点                    ~~~~~~~~~~~~~~~~~~                    parent 父结点
edge
path n 1 n_1 n1 n k n_k nk的路径           ~~~~~~~~~          length 路径长度 k − 1 k-1 k1
ancestor 祖先(多个)         ~~~~~~~         descendant 后代(多个)
depth 根为0,向下依次+1     ~~~     height 树的层数
leaf node 无后代的结点         ~~~~~~~         internal node 有后代的结点
sibling node 同父的结点

full binary tree 若有子树,子树必有两个(a)
complete binary tree 除最后一层全满,最后一层从左到右填上(b)
图例
定理:
leaf node ( n 0 n_0 n0)=internal node( n 2 n_2 n2)+1 叶子结点数=内部结点数+1 (所有满二叉树都成立)
推论:非空二叉树中的空子树数=结点数+1

5.2 Binary Tree Traversals 遍历二叉树

5.2.1 遍历方法

将二叉树的结点简写:N-root, L-left child, R-right child
遍历方法:1.Preorder: NLR, NRL
                 ~~~~~~~~~~~~~~~~                  2.Inorder: LNR, RNL
                 ~~~~~~~~~~~~~~~~                  3.Postorder: LRN, RLN (都是以N为基准)
图例
画一个二叉树: a + b ∗ ( c − d ) − e / f a+b*(c-d)-e/f a+b(cd)e/f (最后计算的在最根部)
图例

5.2.2 用遍历序列还原二叉树

preorderinorderpostorderinorder可唯一地确定一个二叉树。
图例

5.3 Binary Tree Node Implementations 二叉树实现

内部结点IntlNode包括元素和左右两个指针,分别指向leftChildrightchild
叶子结点LeafNode仅包括元素
(二叉树实现和遍历代码见数据结构与算法代码部分)

5.4 Binary Search Tree 二叉查找树(BST)

二叉查找树元素依次增大放置,即满足leftchild < < <root ⩽ \leqslant rightchild

remove函数
(1)0 child:叶子结点,直接移除 (2)1 child:移除该结点并把子结点上移
(3)2 child:找结点代替该结点,一般选右边最小的结点或左边最大的结点
查找树比较平衡时,remove函数的时间复杂度 Θ ( l o g n ) \varTheta(logn) Θ(logn) n n n为树的深度。
图例

(BST代码同样见数据结构与算法代码部分)

5.5 Heaps and Priority Queues 堆与优先队列

heap堆是完全二叉树,分为大顶堆max-heap (root大于两个子结点)小顶堆min-heap (root小于两个子结点)

siftdown 下沉调整算法:结点不符合条件时,与左右子结点进行比较并交换位置,然后继续与子结点进行比较。

void siftdown(int pos){
	while(!isLeaf(pos)){ //stop if pos is a leaf
		int j=leftchild(pos);
		int rc=rightchild(pos);
		if((rc<n)&&Comp::prior(Heap[rc],Heap[j]))
			j=rc;  //如果右子节点存在且其值优先于左子节点的值,则将j更新为右子节点的位置
		if(Comp::prior(Heap[pos],Heap[j]))  
			return;  //如果位置pos的元素优先于j位置的元素,则不需要进行任何交换,函数返回
		swap(pos,j); //move down下移
		pos=j;
	}
}

堆比较平衡时,插入,删除,寻找元素函数的时间复杂度 Θ ( l o g n ) \varTheta(logn) Θ(logn) n n n为树的深度。
(大顶堆实现代码同样见数据结构与算法代码部分)

5.6 Huffman Coding Trees 哈夫曼编码树

weighted path length 带权路径长度
external path weight 外部路径权重
编码步骤
图例
图例
(Huffman编码树实现代码同样见数据结构与算法代码部分)

Chapter 6 Non-Binary Trees

forest:一棵树或多棵树

6.1 ADT for Nodes and General Tree Traversals 树的结点的ADT及遍历

结点与二叉树类似,增加了sibling 同父结点

//General tree node ATD
template <typename E>
class GTNode{
public:
	E value();
	bool isLeaf();
	GTNode* parent();
	GTNode* leftmostChild();
	GTNode* rightSibling(); //return right sibling同父结点
	void setValue(E&);
	void insertFirst(GTNode<E>*);//insert first child
	void insertNext(GTNode<E>*);//insert next sibling
	void removeFirst();
	void removeNext();
}

遍历:只有前序preorder后序postorder遍历

6.2 The Parent Pointer Implementation 父指针表示法

6.2.1 advantages

Parent Pointer:指针由子结点指向父结点
优点
(1)判断2个结点是否在同一树 (找祖父结点,若祖父相同则在同一树)
(2)合并2树(直接将一棵树的root接到另一棵树的root上)

6.2.2 classes 并查集

classes 并查集包括weighted union rule权重合并规则path compression路径压缩
例题:Using the weighted union rule and path compression, show the array for the parent pointer implementation that results from the following series of equivalences on a set of objects indexed by the values 0 through 15. Initially, each element in the set should be in a separate equivalence class. When two trees to be merged are the same size, make the root with greater index value be the child of the root with lesser index value.
(0,2) (1,2) (3,4) (3,1) (3,5) (9,11) (12,14) (3,9) (4,14) (6,7) (8,10) (8,7) (7,0) (10,15) (10,13)
解答
1.题目要求小数在大数上面(指针由大数指向小数)
2.依次加入,加入时同时进行压缩
将(x,y)(例如(4,14))进行合并时,先找到x和y分别的root,比较root大小,若root(x)>root(y),将root(x)指向root(y),合并两树。
图例

6.3 General Tree Implemetations 树的实现

(以下实现都没有代码实现,仅有图示)
1.List of Children 子结点表表示法
Val:结点名
Par:父结点的Index值
图例
2.Left-Child/Right-sibling 左子结点/右兄弟结点表示法
Left:最左子结点位置指针
Right:右边第一个兄弟结点位置指针
图例
3&4.Dynamic Node 两种动态结点表示法
图例图例

6.4 K-ary Trees K叉树

与二叉树类似,分为Full k-ary treesComplete k-ary trees.

6.5 Sequential Tree Implementations 树的顺序表示法

1.用 / 表示空结点(AB/D//CEG///FH//I//)
2.用 ’ 表示内部结点,/ 表示空结点(A’B’/DC’E’G/F’HI)
3.用 ) 表示向父结点退一次<ABD))CEG))FH)I)))>不区分左右结点
图例

根据你提供的错误信息,这个问题是由于没有为选定的 FEAT 目录运行注册(registration)操作导致的。为了进行组分析(group analysis),你需要确保所有选择的 FEAT 目录都已经进行了注册操作并设置正确。 在 FEAT 分析中,注册是将功能图像(functional image)与参考图像(reference image)对齐的过程。这个过程通常包括线性和非线性注册,以确保不同被试之间的功能图像空间对齐。 要解决这个问题,你可以尝试以下几个步骤: 1. 确保所有选定的 FEAT 目录都已经运行了注册操作。检查每个 FEAT 目录中是否存在已经完成的注册文件或结果。如果没有,请运行相应的注册步骤来对齐功能图像。 2. 确保注册过程中使用的参考图像与功能图像相匹配。参考图像通常是一个高分辨率的结构图像(T1-weighted image),用于提供更准确的对齐结果。确保你选择了正确的参考图像,并在注册过程中使用它。 3. 检查 FEAT 目录中的注册设置。确保你在 FEAT 的配置文件或选项中正确启用并设置了注册步骤。具体的设置方式可能因你使用的分析软件而有所不同,可以查阅相关文档或指南来获取详细的指导。 4. 如果你仍然遇到问题,可以考虑重新运行整个 FEAT 分析流程,确保在运行组分析之前已经正确进行了注册步骤。确保每个 FEAT 目录都包含正确的注册结果。 需要注意的是,以上步骤可能因你使用的具体分析软件或工具而有所不同。如果你使用的是特定的软件或工具,建议参考其官方文档或寻求相应的技术支持来获取更准确和详细的帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值