AA5-2-周期性复习干线-追击

数据结构算法与应用:

  1.贪婪算法:

    贪婪算法,把最好的先吃掉。

    贪婪算法的应用首先可以用于货箱装载。对于期望函数为总货箱数的问题中贪婪算法可以给出最优解。但是对于期望函数为总价值的问题来说,看来算法不能保证给出最优解,但是给出的解大部分是最优解,而且与最优解的误差最多能达到25%。

      在利用贪婪法求解卧箱装载的总箱子数最多的问题是思路是。{首先对需要装载的货物进行排序升序排序。然后以升序的方式将货物依次装进箱子内,自然而然就是总箱子数最多的解了。}

      利用贪婪算法求解,总价值最高的。装箱方式与上述相同。给出的是一个可行解。

    贪婪算法可以应用于拓扑排序。算法目标在离散数学中,已经有了明确定义。算法思路是。{首先计算所有顶点的入度。入度可以利用顶点迭代器以及一个for vertex-while nextVertex嵌套循环来完成。那么入度为0的顶点就是入口。将直接入口压入栈中。依次处理。每次处理一个压入栈中的顶点时,首先需要将其出栈。然后将这个顶点加入拓扑排序的数组中。随后需要消除这个顶点,对其他点的影响,也就是说这个点将从图中消失。因此再次利用顶点迭代器对所有其他顶点的入度进行减1。在这个过程中,如果对某个顶点的入度进行减一完成后其入度变成0,那么说明这一定是下一个图结构的入口。因此将这一个顶点加入栈中等待之后再进行处理。当拓扑排序的数组满足了所有顶点均在其内之后,完成排序。}---P428

    应用于二分覆盖。算法的目标是。[获得一个最少顶点实现二分覆盖的点集]

            算法的思路是。{维护一个数据内容是各个顶点覆盖对方未被覆盖节点的数目news。也就是它的出度。另一个数组对方节点未被覆盖的索引数组covered。算法部分。如果news[i]不为零,则找到news最大的一个 i.啊,随后将其记录进结果数组中。随后消除它的影响,首先。把所有连接于V的顶点。全部标记为已覆盖,并且是受到影响的己方顶点news--。重复这个循环,如果最后有顶点未被覆盖,则2分覆盖失败,否则就成功。}

    Dijkstra法 单源最短路问题。算法目标是。[将一个表示权值的邻接矩阵二维数组中 [s][i] 元素更新成从s 到 i 的最短距离。]

            算法思路是。{首先,从起点开始,将起点的所有的后继顶点全部纳入待处理数组。随后以待处理数组中的每一个顶点为基础从[s][i] 最小的顶点开始,对其所有后继顶点的 a[s][i]值进行更新。在直连s路和间路之间选择更小者。完成更新。随后将此顶点删除。如果a[s][i] 更新了,说明此节点是间路最小,也就是说,必须借助前一个顶点j来到i,因此在路径数组中将i连接到j上。并将j加入待处理数组中。}    另外此算法支持递归,但复杂度太高。后续会有更好的动态规划算法。

    最小生成树

      以下几种算法是否成功只需要看最后的生成树大小是否为vertex-1。

      Kruskal。算法思路。(数组为核心){每次都在剩余的边里找一条最小权值的边(通过堆排序建立边的三元组数组),硬生生拼到图里。如果拼进去会成环就扔掉(利用特制Union结构查询两顶点是否存在关系,如果不存在就加上,并返回不存在,反之返回存在。这一功能也可以通过其他方式实现。散列,跳表都是不错的选择。)。直到处理完所有边。}

      Prim。算法思路。(集合为核心){每次都在剩余边中找一条权值最小且能够让树进行生长的边加入。处理完所有边。}

      Sollin。就是一个多线程的Kruskal算法。

  2.分治算法:

    分而治之。

    很经典的就是试毒问题。128瓶毒药只需要7只老鼠就知道哪瓶有毒。把药作为外部节点接到一个完全二叉树上去。从根节点的下一层开始每只老鼠负责一层。运气好一路排除到毒药的位置。运气不好死一路老鼠最后定位到毒药的位置。

    残缺棋盘。目标{将缺一块的2K方阵用三格直角瓦覆盖满} 思路{每次都放在十字中心,让不缺的三个象限瓜分。然后递归下去。。。}

    归并排序。分块排序,然后相邻merge(归并)。时间复杂度O(nlogn)这是严格的上下确界。自然归并给出了浮动。改变分组策略,分界点变为第一个逆序数。

    快排。{把最大的元素放置到最右端。将数组二分,接着取区间左端点为支点,借助两个游标从左右端点相向行驶,路程中任意一方遇到不满足相对于支点左小右大的元素就停下,如果双方均停下则交换该处元素。否则将行驶直到相遇,完成相对于支点两侧的区间排序。接着将支点与中游标相遇点互换。然后对支点两侧的区间继续这一过程。直到区间长度为1。}复杂度 O(nlogn) 最坏O(n2)  三值取中快排优化了支点的选择方式。一定程度上有利于将O(n2)的复杂度向O(nlogn)收缩。

    选择。问题目标是。{找到数组中第k小的元素}。思路。{将快排的思路进行一下改进。在快排的过程中利用支点的性质,每次找到支点后判断一次支点坐标是否为所需要的排序位置。如果还没有找到,则将程序向可能存在所需位数元素的位置进行递归。直到递归完成。}复杂度为 O(n)

    相距最近的点对。思路。{以x坐标的中点为界将点划分为两组,分别找到两组点的最小距离。并记录最小距离δ。随后在坐标系中以δ为基准从分界处将两组点中距离分界处太远的点排除掉。随后对于每个区域内的点,以其中一个点为基准以δ为尺度再一次对对面一组中点的y坐标进行排除。最后只需要在比较区内进行全部距离的运算即可。基准状态是比较三个点之间的最小距离。}这事实上是一个简单的递归程序。复杂度 (nlogn)。

    递归方程复杂度求解。对于递归部分的递归方程 为形如t( n ) = a * t( n / b ) + g( n )的典型归并递归方程。其复杂度为 g(n) / n^ (logba)。

    复杂度下限。复杂度上限为O(f(n)),确界为Θ(f(n)),下限为 Ω(f(n)) ,在最坏情况下的下限可以很好的反映算法的复杂度。

        最小最大问题的下限——「3n/2| - 2 推导方式为——通过状态空间表示法找到最短计算转移路径。通过(n,0,0,0) 注:参数为(未判定,最大候选,最小候选,咸鱼)转移到 ( 0,1,1,n-2) 每次 未判定内的参数比较会向最大候选,最小候选参数对称分裂。一共n/2次,然后最大候选,最小候选中再自己比较,每次都可以向 咸鱼中转移1 因此一共有「n/2| + 「n/2|  -1 + 「n/2| -1 = 「3n/2| -1次。

        排序问题的下限—— O(nlog(n)) 利用决策树证明更容易理解。将每种排序都作为一个外部节点接到二叉树上共n!个。显然从根节点向叶子节点的一条路就是排序的过程。次数也就是树的高度。即对于高度h,其叶子节点最多有2h个。因此。高度至少为「log2n! | = Ω(nlogn)

  3.动态规划

    最短路问题。(主要指所有两两点之间的最短路问题。对于单源最短路问题完全可以通过最小生成树或者dijsktra法进行解决。)思路。{利用状态转移方程 distance[i][j] = min(disctance[i][j],distance[i][k]+distance[k][j]) 从1,1开始按照行主序,将已经被邻接矩阵初始化过的权值矩阵进行更新,如果在更新过程中状态转移方程使用了第二项,则将k值更新到ka[i][j]中,将工具点进行更新。k代表的是工具点,用于跳转,起始为1,置于基层循环,等待i,j遍历完成后。k = 1时,以1为工具点的所有权值就被更新完毕了。此后继续将k = 2 ... n全部更新完毕。 现在只需要访问 f(i,j) { if ka[i][j]==0;输出;f(i,ka[i][j]) ; f(ka[k][j],j) ;}   就可以输出任意两个点之间的最短路了。 }

posted @ 2020-11-14 21:09  Zebro  阅读(139)  评论(1编辑  收藏  举报