# 完成在 10.2.3 节末尾描述的抽样算法的分析,并解释 和 的值如何选择
让 成为样本 中元素 的秩,如果样本 的元素来源于, 则有
如果 是五分项中第三大的的元素,则有
我们选择 和 以便于得到下式
当 允许有许多方差后,则有
如果, 化简得
最终得到
又因为, 最终 和 选择
,.
# 为什么 Strassen 算法在 2×2 短阵的乘法不使用可交换性是重要的
因为矩阵乘法没有交换性。
# 证明下列贪婪算法均不能进行链式短阵乘法。在每一步
# 计算最节省的乘法。
假设三个矩阵,分别是,,, 如果, 则使用贪心算法可以,但反之贪心算法则没法成功。
# 计算最昂贵的乘法。
# 计算两个矩阵 和 之间的乘法使得在 中的列数最小,使用上面法则之一
上面两个问同理。
# 编写一个程序计算矩阵乘法的最佳顺序。注意,程序要显示具体的顺序
回溯算法技巧的典型应用。
/* | |
* Compute optimal ordering of matrix multiplication. | |
* C contains number of columns for each of the N matrices. | |
* C[0] is the number of rows in matrix 1. | |
* Minimum number of multiplications is left in M[1][N]. | |
* Actual ordering is computed via. | |
* another procedure using LastChange. | |
* M and LastChange are indexed starting at 1, instead of 0. | |
* Note: Entries below main diagonals of M and LastChange are | |
* meaningless and uninitialised. | |
*/ | |
void OptMatrix(const long C[], int N, long M[][MaxSize], long LastChange[][MaxSize]) { | |
long ThisM; | |
for (int Left = 1; Left <= N; Left++) { | |
M[Left][Left] = 0; | |
} | |
for (int K = 1; K < N; K++) { | |
for (int Left = 1; Left <= N -K ; Left++) { | |
// for each position | |
int Right = Left + K; | |
M[Left][Right] = Infinity; | |
for (int i = Left; i < Right; i++) { | |
ThisM = M[Left][i] + M[i + 1][Right] | |
+ C[Left - 1] * C[i] * C[Right]; | |
if (ThisM < M[Left][Right]) { | |
// update min | |
M[Left][Right] = ThisM; | |
LastChange[Left][Right] = i; | |
} | |
} | |
} | |
} | |
} |
# 编写个例程从 10.3.4 节中的算法重新构造那些最短路径。
依旧使用的是 Dijkstra 算法。
# 编写在跳跃表中执行插入、删除以及查找的例程
删除很麻烦,还有删除。
// Insert a new element node | |
void Skiplist_Insert(Skiplist S, int Data) { | |
/* First step: find the insertion position of each layer */ | |
// last[i]: The predecessor node of the insertion position at level i | |
Skiplist_Node last[MAX_LEVEL]; | |
Skiplist_Node pos = S->Head; | |
for (int i = S->Level - 1; i >= 0; i--) { | |
while (pos->Next[i] != NULL && pos->Next[i]->Data < Data) | |
pos = pos->Next[i]; | |
last[i] = pos; | |
} | |
/*Second step: generate new nodes and layers*/ | |
// int level = RandLevel(); // The number of layers of the new node | |
int level = RandInt(1, 16); | |
// if number of layers of the new node is larger than | |
// layers of the original node. | |
// It is necessary to supplement the high bits of the last array, | |
// and the head will point to this node | |
if (level > S->Level) { | |
for (int i = S->Level; i < level; i++) | |
last[i] = S->Head; | |
S->Level = level; | |
} | |
/*Third step: each layer performs insertion*/ | |
Skiplist_Node Node = Skiplist_NewNode(Data, level); | |
for (int i = 0; i < level; i++) { | |
Node->Next[i] = last[i]->Next[i]; | |
last[i]->Next[i] = Node; | |
} | |
// Update number of nodes | |
S->Num++; | |
} |
// Return whether Data is in the skip list. | |
// Actually find data in the skip list | |
static bool Skiplist_IsHas(Skiplist S, int Data) { | |
Skiplist_Node pos = S->Head; | |
for (int i = S->Level - 1; i >= 0; i--) { | |
while (pos->Next[i] != NULL && pos->Next[i]->Data < Data) | |
pos = pos->Next[i]; | |
} | |
pos = pos->Next[0]; | |
return pos != NULL && pos->Data == Data; | |
} |
// Delete one node from the skip list | |
bool Skiplist_Delete(Skiplist S, int Data) { | |
/* First step: Find the predecessor node of | |
* the deletion position of each layer. | |
*/ | |
Skiplist_Node last[MAX_LEVEL]; | |
Skiplist_Node pos =S->Head; | |
for (int i = S->Level - 1; i >= 0; i--) { | |
while (pos->Next[i] != NULL && pos->Next[i]->Data < Data) | |
pos = pos->Next[i]; | |
last[i] = pos; | |
} | |
// The node will be deleted | |
pos = pos->Next[0]; | |
if (pos != NULL && pos->Data != Data) return false; | |
/*Second step: each layer performs deletion*/ | |
for (int i = S->Level - 1; i >= 0; i--) { | |
if (last[i]->Next[i] == pos) | |
last[i]->Next[i] = pos->Next[i]; | |
} | |
/*Third step:remove the invalid layers | |
* that may be caused by deleting nodes | |
*/ | |
Skiplist_Node tmp = S->Head; | |
while (S->Level > 1 && tmp->Next[S->Level - 1] == NULL) | |
S->Level--; | |
S->Num--; | |
Skiplist_FreeNode(pos); | |
return true; | |
} |
# 给出跳跃表操作的期望时间为 的正式证明
大致证明见跃表的推导和数学证明。
# 实现收费公路重建算法
// x[] is a collection of points. | |
// Dset[] is a collection of distance of point to point. | |
// N is the number of point. | |
int turnPike(int X[], int Dset[], int N) { | |
// Include the largest and smallest points into the vertices. | |
X[1] = 0; | |
X[N] = Dset[N * (N - 1) / 2]; | |
// Set the maximum distance to -1, which means empty. | |
Dset[N * (N - 1) / 2] = -1; | |
return Place(X, Dset, N, 2, N-1); | |
} |
# 写出三连游戏棋剩下的步骤。
直接看 tic-tac-toe 源码吧,实在太多行了。