数据结构重读 – 树和等价问题(并查集)

数据结构这书感觉和之前没读过一样……以前从来没发现树这章还讲了并查集……

若R是集合S上的一个等价关系,则由这个等价关系可以产生这个集合的唯一划分。

如何划分等价类

假设集合S有n个元素,m个形如(x, y),的等价偶对(x, y都是集合S中的元素)。

(1)令S中每个元素各自形成一个只含单个成员的子集,记作S1, S2, ..., Sn。
(2)依次读入m个偶对,对每个读入的偶对(x, y),判定x和y所属的集合,若他们还不属于同一集合,设x属于Si,y属于Sj,则合[......]

继续阅读

数据结构重读 - 树和森林

树的存储,不再限于二叉树了。

1、双亲标示法
虽然每个结点可能有多个孩子,但是每个孩子只可能有一个双亲,这是固定的。
于是有了双亲标示法。
每个孩子存在数组中,孩子记录其双亲的位置。
如果根据某个孩子找双亲,可以几乎在常数时间搞定(反复调用PARENT(T, X),直到X为根为止)。
但是如果要从树根往下遍历求孩子结点,则需要遍历整个数组,会很慢。

typedef struct PTNode
{
int data;
int parent;
};

typdef[......]

继续阅读

数据结构重读 – 线索二叉树

我们在二叉树上的先序、中序、后序遍历都是递归或者非递归完成的。

我们只能找到左、右孩子,而不能找到先、中、后序遍历序列下,元素的前驱和后继。

为此,我们可以设计线索二叉树,定义如下:
struct BiTreeThd
{
int data;
bool lflag, rflag;
struct BiTreeThd* lchild, *rchild;
};
如上,多了lflag和rflag:
(1)当有左/右孩子的时候,lflag/rflag为0。[......]

继续阅读

求子数组之和的最大值

编程之美上的一道题,今天在别的地方看别人用贪心写的,真心觉得不对,所以做了一下。

一个有N个元素的一维数组(a[0], a[1]....a[n-1]),我们定义连续的a[i] ~ a[j],0<= i, j <=n-1为子数组。

显然这个数组中包含很多子数组,请求最大的子数组之和。

如果不想时间复杂度,用遍历所有可能子数组,然后找出最大值就可以了。

现在如果要求时间复杂度最小,那么肯定是要DP解的。

我们假设定义两个数组:

all[i]:表示从i~[......]

继续阅读

带min和max辅助函数的栈

设计一个特殊的栈,包含 min 函数。能够得到栈的最小元素。

要求函数 min、push 以及 pop 的时间复杂度都是 O(1)。

分析

由于时间复杂度的要求,我们不能用其他方法了,最简单的就是用空间换时间,给每个元素加一个min元素,表示压栈到现在最小的元素。

这样每次push时候,维护下data[top-1].min和当前val,取min值设到data[top].min即可。注意top=0时的特殊情况,min就是val。

特别提醒:企图整个栈共用一个min或者[......]

继续阅读