数据结构与算法
EmberWn
初学者
展开
-
平方探测的另一种插入方式
如果把新元素插入到搜索路径的第一个inactive单元,这样能够回收一个deleted单元,潜在的节省了空间。查找元素位置时分两种情况,一种是元素已经在表中,则返回元素的位置。另一种是元素不在表中,则返回第一个inactive单元位置。添加新的变量firstPos记录第一个inactive单元位置。findPos代码如下int findPos(const HashedObj& x)const原创 2017-07-11 13:33:48 · 276 阅读 · 0 评论 -
拓扑排序
拓扑排序是针对有向无圈图的顶点的的一种排序。每个顶点拥有入度,邻接表,拓扑序三个成员。首先找到入度为零的顶点将其放入队列,然后将其出队,删除顶点和它的边。然后更新邻接顶点的入度,如果入度为零,则将顶点放入队列,直到队列为空。最后输出拓扑序。头文件#include <vector>class Graph{public: explicit Graph(int vertexNum):v(ver原创 2017-08-05 15:04:33 · 255 阅读 · 0 评论 -
随机数生成器
头文件static const int A=48271;static const int M=2147483647;static const int Q=M/A;static const int R=M%A;//x[i+1]=Ax[i]modMclass Random{public: explicit Random(int initialValue=1);//x[0]种子原创 2017-08-19 21:31:20 · 1250 阅读 · 0 评论 -
无权最短路径选择
图类的数据成员除了顶点的集合外还有一个记录起始顶点的数据成员。顶点的数据成员有距离起始顶点的最短距离,邻接表,最短路径上顶点的上一个顶点三个数据成员。首先将起始顶点入队,距离为零,然后将其出队,更新其邻接顶点的距离并把它们放入队列。重复到队列为空为止。头文件#include <vector>#include <climits>#include <iostream>class Graph{pu原创 2017-08-05 17:15:07 · 627 阅读 · 0 评论 -
测试一个大数是否是素数
如果P是素数,且0int witness(const int & a,const int & i,const int & n){ if(i==0) return 1; int x=witness(a,i/2,n); if(x==0) return 0; int y=(x*x)%n; if(y==1&&x!=1&&x!=n-1)原创 2017-08-20 20:49:51 · 366 阅读 · 0 评论 -
桶排序与基数排序与计数基数排序
输入只有大小小于M的正整数,可以采用桶式排序。#include <iostream>#include <vector>#include <string>using namespace std;//基数排序void radixSort(vector<string> & arr,int stringLen){ const int BUCKETS=256; vector<vec原创 2017-07-28 20:40:40 · 253 阅读 · 0 评论 -
可变长度的基数排序
字符串的比较是从高有效位开始依次比较,和长度没有太大关系。因此可以理解为末尾补零,长度相同。先将字符串按长度进行排序,然后从低有效位开始比较,对零(没有的位)不进行处理(已经在正确的位置)。#include <iostream>#include <vector>#include <string>using namespace std;void radixSort(vector<string>原创 2017-07-28 22:09:30 · 334 阅读 · 0 评论 -
生成迷宫并找出走出迷宫的路径
利用不相交集类生成迷宫,具体见 http://blog.csdn.net/blubluhao/article/details/76445377然后利用无权图的最短路径选择找出走出迷宫的路径,具体见 http://blog.csdn.net/blubluhao/article/details/76726887首先生成迷宫,然后利用已经生成的迷宫构建出一个图。迷宫的所有单元构成图的顶点,单元间没有墙原创 2017-08-06 21:17:18 · 2017 阅读 · 0 评论 -
回溯算法--三连游戏(人机对战)
程序的核心部分在于计算机如何选择下棋的位置。采用的策略叫作极小极大策略。通过一个赋值函数来给一个位置的“好坏”定值。能使计算机获胜的位置得到值+1;平局得到0;使计算机输棋的位置得到值-1。通过考察盘面就能够确定输赢的位置叫作终端位置。 如果一个位置不是终端位置,那么该位置的值通过递归假设双方最优棋步而确定。这叫做极小极大策略,因为下棋的一方(人)试图极小化这个位置的值,而另一方(计算机)却要使它原创 2017-08-24 16:47:14 · 554 阅读 · 0 评论 -
回溯算法--收费公路重建问题
通过点与点之间的距离重新构造出点集。距离集大小为N(N-1)/2,N为点的个数。驱动程序#include <iostream>#include <vector>#include <set>using namespace std;bool turnpike(vector<int> & x,multiset<int> d,int n){ bool place(vector<int> &原创 2017-08-21 18:47:21 · 800 阅读 · 0 评论 -
深度优先搜索寻找割点
如果无向连通图不存在删除后剩下的图不再连通的顶点,则该图为双连通。如果不是双连通的图,那么那些删除后剩下的图不再连通的顶点叫做割点。 执行深度优先搜索,按照搜索顺序给顶点编号Num。然后后序遍历,计算顶点的Low值,其为顶点通过该序(可能包含背向边)能到达的最小顶点。 Low(v)为各项中的最小值: 1、Num(v) 2、所有背向边(v,w)中的最低Num(w) 3、所有边(v,w)中的最原创 2017-08-14 21:07:44 · 1199 阅读 · 0 评论 -
配对堆
配对堆采用左儿子和右兄弟的表示方法。存在额外的链,如果节点是最左儿子,则链指向父节点,如果不是,则指向左兄弟。把这个数据成员叫做prev。 配对堆的基本操作有merge、insert、deleteMin、decreaseKey。合并时让较大根的子堆成为另一个最左的儿子。如下图所示: insert操作返回Position对象,传给decreaseKey操作使用。insert操作是mer原创 2017-09-13 16:42:58 · 1336 阅读 · 0 评论 -
三连游戏优化--α-β裁剪
findCompMove操作希望得到返回值中的极大值,而findHumanMove操作返回极小值。将findCompMove操作得到的尝试性的极大值(α)传给findHumanMove,如果findHumanMove尝试性的极小值(β)小于这个极大值,则立马返回,无需尝试后面的情况。此为α裁剪,对称情况即为β裁剪。尝试性的意思是指目前已经得到的极大值或者极小值。α-β裁剪能显著的改进搜索的范围。代码原创 2017-09-06 16:19:11 · 352 阅读 · 0 评论 -
红黑树--自顶向下插入
红黑树是具有下列着色性质的二叉查找树: 1、每一个节点红或者黑 2、根是黑色的 3、如果一个节点是红色的,那么它的子节点必须是黑色的 4、从一个节点到一个null指针的每一条路径必须包含相同数目的黑色节点在执行插入操作时,如果父节点为黑节点则直接插入红节点。但如果父节点是红节点,如果插入黑节点则会违反法则4,黑色节点数目变多。如果插入红节点则会违反法则3,出现连续的红节点。因此采用旋转操作和原创 2017-09-07 16:08:54 · 632 阅读 · 0 评论 -
Treap树
Treap树的节点具有优先级,优先级是在建立节点时随机指定的。Treap树是节点优先级满足堆序的二叉查找树:任意节点的优先级至少和它的父节点的优先级一样大。根节点优先级最低。nullNode节点优先级为无穷。头文件#include <climits>#include "UniformRandom.hpp"template <typename Comparable>class Treap{p原创 2017-09-08 21:10:47 · 301 阅读 · 0 评论 -
动态规划—矩阵乘法排序
矩阵乘法满足结合律,因此可以选择不同的乘法顺序来进行。矩阵乘法进行的次数等于两个子序列各自乘法次数加上两个子序列做一次乘法所需次数。 Mleft,right=Mleft,i+Mi+1,right+cleftcicrightM为乘法次数,c[i]等于第i个矩阵的列数。c[0]为第一个矩阵的行数,c[i-1]为第i个矩阵的行数 由于递归在一些情况下会重复计算,导致效率急剧降低,因此需要将递归变为非递原创 2017-08-18 18:31:37 · 543 阅读 · 0 评论 -
Dijkstra算法那--赋权最短路径
相对于无权最短路径,赋权最短路径多了一个成员know来标记顶点是否已知。从未知的顶点中找到路径最短的顶点,标记为已知,然后如果它的未知邻接顶点距离dw大于dv+Cv,w,则更新dw。头文件#include <vector>#include <map>#include <iostream>static const int MAX=10000;using namespace std;class原创 2017-08-11 17:17:58 · 753 阅读 · 0 评论 -
优先队列(二叉堆)
二叉堆的主要操作有deleteMin(),insert()和buildHeap()。deleteMin()和buildHeap()采用下滤,insert()采用上滤。#include <vector>template <typename Comparable>class BinaryHeap{public: explicit BinaryHeap(int capacity=100);原创 2017-07-15 22:17:07 · 267 阅读 · 0 评论 -
左式堆
左式堆核心是合并操作。增加了新的数据成员,零路径长(npl)。左儿子的npl不小于右儿子,父节点的npl等于右儿子npl加1。在合并操作中要保持左式堆的性质并更新节点的npl。合并的方式为递归的将具有较大根值的堆与具有较小根植的堆的右子树合并。template <typename Comparable>class LeftistHeap{public: LeftistHeap();原创 2017-07-17 10:35:53 · 377 阅读 · 0 评论 -
不相交集类
union采用按高度求并,find采用路径压缩。存储的高度值为实际高度的负值减一。#include <vector>using namespace std;class DisjSets{public: explicit DisjSets(int numElements); int find(int x)const; int find(int x); void u原创 2017-07-30 10:30:29 · 310 阅读 · 0 评论 -
插入排序与希尔排序
#include <iostream>#include <vector>#include <functional>using namespace std;template <typename Iterator ,typename Comparator >void insertionSort(const Iterator & begin,const Iterator & end,Compara原创 2017-07-21 10:40:28 · 179 阅读 · 0 评论 -
堆排序
先用线性时间建立一个堆,然后将堆的最后一个元素与第一个元素交换。将堆的大小减一并执行下滤。#include <vector>using namespace std;template <typename Comparable>void heapsort(vector<Comparable> & a){ for(int i=a.size()/2-1;i>=0;--i) {原创 2017-07-21 15:52:35 · 161 阅读 · 0 评论 -
堆——二项队列
二项队列由一系列二项树组成,每个高度只允许一棵二项树。每棵树Bk由一个根和Bk-1…B0组成。删除最小值操作是先找到最小根值的树,然后删掉树根,得到新的一组二项队列Bk-1…B0。将两个队列合并,便完成了删除最小值操作。#include <vector>template <typename Comparable>class BinomialQueue{public: BinomialQ原创 2017-07-18 10:32:09 · 351 阅读 · 0 评论 -
数据结构——散列表
分离链接散列表和平方探测散列表#include <vector>#include <list>#include <string>#include <algorithm>#include <cmath>//判断一个数是否是素数bool isPrime(int size){ //保证了size是奇数,因此因子也是奇数 for(int i=3;i<=sqrt(size);i+=原创 2017-07-08 11:10:37 · 227 阅读 · 0 评论 -
杜鹃散列
杜鹃散列表通常通过一个拥有多个散列函数的大表来实现,这些散列函数探测整个大表。插入时首先依次尝试所有散列函数,一旦找到空位便插入。如果试完所有散列函数仍未找到空位,便随机踢出一个,记录最后被踢出的位置(如果下次随机出来的位置与最后被踢出的位置相同,则重新随机)然后将被踢出去的项插入散列表,重复上述步骤。如果经过一定次数的尝试,仍未成功插入,则更换一组散列函数(不改变表的大小)。若更换五组散列函数后仍原创 2017-07-10 13:09:38 · 1300 阅读 · 0 评论 -
应用不相交集类生成迷宫
应用不相交集类(采用高度求并和路径压缩查找)构建一个n阶正方形迷宫,迷宫拥有n的平方个单元,每个单元拥有三个数据成员。一个数据成员存储父节点,如果是根节点则存储树的高度的负值减一。另两个数据成员分别代表单元的下侧墙和单元的右侧墙。再额外添加上边框和左边框就构成迷宫。 一开始所有的单元相互不连通,构建时随机选择一堵可以拆的墙,如果墙两侧的单元不连通,联通他们并拆掉墙。如果联通就不进行操作。进行到最后原创 2017-07-31 15:41:41 · 930 阅读 · 0 评论 -
归并排序
#include <vector>using namespace std;template <typename Comparable>void mergeSort(vector<Comparable> & a){ vector<Comparable> tmpArray(a.size()); //存放归并结果的数组 mergeSort(a,tmpArray,0,a.size()-原创 2017-07-22 16:10:54 · 167 阅读 · 0 评论 -
递归排序
#include <vector>using namespace std;template <typename Comparable>void SORT(vector<Comparable> & items){ if(items.size()>1) { vector<Comparable> smaller; vector<Comparable>原创 2017-07-22 20:51:30 · 173 阅读 · 0 评论 -
词梯游戏
//无权最短路径问题#include <iostream>#include <unordered_map>#include <string>#include <vector>#include <queue>using namespace std;unordered_map<string,string>findChain(const unordered_map<string, vecto原创 2017-08-07 21:52:32 · 783 阅读 · 0 评论 -
快速排序
快速排序的优点在于在合适的位置进行分割并且不用额外的数组。#include <vector>using namespace std;template <typename Comparable>void quickSort(vector<Comparable> & a){ quickSort(a,0,a.size()-1);}//三位中值分割template <typename Co原创 2017-07-23 21:02:44 · 170 阅读 · 0 评论 -
快速选择
快速选择和快速排序类似,将数组分为S1和S2。当K值小于S1的的长度时,对S1进行递归。当k值刚好等于pivot时,那么已经找到了。当k值大于S1长度加一时,对S2进行递归。最后K始终在数组下标k-1的位置。#include <iostream>#include <vector>using namespace std;template <typename Comparable>void ins原创 2017-07-25 10:13:14 · 183 阅读 · 0 评论 -
用回溯算法解决八皇后问题
八皇后问题是指在一个8乘以8的棋盘上放置八个皇后,它们不能在同一行同一列以及同一对角线上,有多少种放法。解决思路:用二维数组表示棋盘,初始为全0,放置皇后则将值置1。当全部放置好了,就将计数器加1。最后输出计数器。无论成功还是失败,都进行回溯。#include <vector>#include <iostream>using namespace std;//负责放置皇...原创 2018-03-18 22:54:44 · 371 阅读 · 0 评论