Tag Archives: 重读

数据结构重读 - 矩阵的压缩和存储

矩阵在数值运算中很常见,本节关注如何存储矩阵的元,从而使矩阵的各种运算能有效进行。

如果矩阵中有许多相同值的元素或者很多零元素。有时为了节省存储空间,可以对这类矩阵进行存储压缩,称为稀疏矩阵。更进一步的,如果稀疏矩阵的相同值或零元素分布还是有规律的,我们可以称他们为特殊矩阵

对称矩阵

例如:

1 2 4
2 3 5
4 5 6

我们可以为每一对称元分配一个存储空间,即可以将n^2个元压缩存储到n*(n+1)/2个空间中。

假设在线性(一元)数组中存储,下[......]

继续阅读

数据结构重读 - KMP串匹配算法

设:m是模式串pattern的长度,n是主串长度

传统的字符串匹配(暴力法)的时间复杂度是O(n*m)。

而KMP串匹配算法可以将时间复杂度降为O(n+m),这需要一个额外的预处理O(m)。

KMP优化的地方在于:当出现字符失配的情况时,无需回溯i指针,而是利用已经匹配的部分,将模式串尽可能向右滑动一部分。

实际上:KMP的预处理本身就是一个模式串pattern“自我匹配”的过程。因此,预处理和kmp算法主体非常神似。

预处理过程:
int get_next(ch[......]

继续阅读

数据结构重读 – 循环队列

队列也可以用顺序存储表示。定义还是一样的:从队尾rear推入元素。从头部head拿出元素,是FIFO。

与链式存储一致,我们仍然需要附设两个指针front和rear分别表示队列头元素和队列元素的位置。初始时front=rear=0是队列空的条件。

每当插入新的队列元素时,尾指针将增1.删除队列头元素时,头指针增加1。即非空队列中:头元素总是指向队首元素,而尾指针总是指向队尾元素的下一个位置。

除了基本的顺序存储外,我们还可以使用循环数组来构造一个循环队列

在循环队列中,[......]

继续阅读

数据结构重读 – 队列 & 双端队列

队列(queue)是一种先进先出(FIFO)的线性表。只允许在一端进行插入,而在另一端删除元素。

允许插入的一端叫做队尾,允许删除的一端叫做队头。

双端队列(deque):限定插入和删除操作在表两端进行的线性表。

双端队列在一些限定条件下可以退化为:
(1)普通队列(只能在一端插入而另外一端删除)
(2)两个栈底相连的栈

队列 / 双端队列的定义:

由于可以在双端操作,所以肯定得有一个head,一个rear(tail)。我觉得确实用一个多的空头表示比较合适,然后[......]

继续阅读

数据结构重读 – 递归与汉诺塔

堆栈与递归是相辅相成的。

比如Fibnacci数列就是递归定义:

Fib(n) = Fib(n-1) + Fib(n-2) (n>=2) Fib(0) = 0 Fib(1) = 1

Fibnacci数列:1, 1, 2, 3, 5, 8, 13, 21, ....

说到这里再写个Fibnacci的通项公公式:

这个还是很无敌的……

然后再一个例子是书上的Ackerman函数:

 

转回经典的汉诺塔问题:假设有三个命名为X,Y[......]

继续阅读