1、1河南大学软件学院计算机应用单付尚2009-3-9常用算法大全1【程序 1-1】 欧几里德递归算法 .1【程序 1-2】 欧几里德迭代算法 .1【程序 1-3】 Gcd 的连续整数检测算法 .1【程序 1-4】 求 Fn 1【程序 1-5】 逆序输出正整数的各位数 .1【程序 1-6】 汉诺塔问题 .2【程序 1-7】 排列产生算法 .2【程序 2-1】 求数组元素累加之和的迭代程序 .3【程序 2-2】 求数组元素累加之和的递归程序 .3【程序 2-3】 矩阵乘法 .3【程序 3-1】 伸展树类 .4【程序 3-2】 旋转函数 .4【程序 3-3】 伸展树插入 .5【程序 3-4】 跳表结点
2、类 .6【程序 3-5】 跳表类 .7【程序 3-6】 构造函数 .7【程序 3-7】 级数分配 .7【程序 3-8】 插入运算 .8【程序 4-1】 ENode 类 .9【程序 4-2】 图的广度优先遍历 .9【程序 4-3】 图的深度优先搜索 .10【程序 4-4】 计算 d 和 Low.11【程序 4-5】 求双连通分量 .11【程序 4-6】 与或树及其结点类型 .12【程序 4-7】 判断与或树是否可解算法 .12【程序 4-8】 广度优先生成解树的算法框架 .13【程序 5-1】 分治法 .14【程序 5-2】 一分为二的分治法 .14【程序 5-3】 可排序表类 .14【程序 5
3、-4】 求最大最小元 .15【程序 5-5】 分治法求最大、最小元 .15【程序 5-6】 二分搜索算法框架 .16【程序 5-7】 对半搜索递归算法 .16【程序 5-8】 对半搜索的迭代算法 .172【程序 5-9】 Merge 函数 .17【程序 5-10】 两路合并排序 .17【程序 5-11】 分划函数 .18【程序 5-12】 快速排序 .18【程序 5-13】 Select 函数 19【程序 5-14】 线性时间选择算法 .19【程序 6-1】 贪心法 .20【程序 6-2】 背包问题的贪心算法 .20【程序 6-3】 带时限作业排序的贪心算法 .21【程序 6-4】 带时限的作
4、业排序程序 .21【程序 6-5】 使用并查集的带时限作业排序程序 .22【程序 6-6】 两路合并最佳模式的贪心算法 .22【程序 6-7】 最小代价生成树的贪心算法 .23【程序 6-8】 普里姆算法 .23【程序 6-9】 克鲁斯卡尔算法 .25【程序 6-10】 迪杰斯特拉算法 .26【程序 6-11】 多带最优存储 .27【程序 7-1】 多段图的向前递推算法 .27【程序 7-2】 弗洛伊德算法 .28【程序 7-3】 矩阵连乘算法 .28【程序 7-4】 矩阵连乘的备忘录方法 .29【程序 7-5】 求 LCS 的长度 31【程序 7-6】 构造最长公共子序列 .31【程序 7-
5、7】 构造最优二叉搜索树 .32【程序 7-8】 0/1 背包的递归算法 .32【程序 7-9】 0/1 背包算法的粗略描述 .33【程序 7-10】 0/1 背包最优解值算法 .34【程序 7-11】 0/1 背包最优解算法 .35【程序 712】Johnson 算法 35【程序 8-1】 递归回溯法 .36【程序 8-2】 迭代回溯法 .36【程序 8-3】 蒙特卡罗算法 .37【程序 8-4】 n-皇后问题的回溯算法 37【程序 8-5】 子集和数的回溯算法 .383【程序 8-6】 图的 m-着色算法 38【程序 8-7】 哈密顿环算法 .39【程序 8-8】 0/1 背包算法 .40
6、【程序 8-9】 批处理作业调度算法 .42【程序 9-1】 分枝限界算法 .43【程序 9-2】 基于上下界函数的 FIFO 分枝限界法 44【程序 9-3】 基于上下界的 LC 分枝限界法 44【程序 9-4】 带时限的作业排序 .46【程序 9-5】 类声明 .48【程序 9-6】 上下界函数 .49【程序 9-7】 0/1 背包问题的 LC 分枝限界法 49【程序 9-8】 批作业类和活结点结构 .50【程序 9-9】 下界函数 .51【程序 9-10】 批处理作业调度 LCBB 算法 52【程序 10-1】 不确定搜索算法 .53【程序 10-2】 不确定排序算法 .53【程序 10
7、-3】 最大集团判定问题不确定算法 .54【程序 10-4】 可满足性问题的不确定算法 .54【程序 11-1】 标识重复元素的拉斯维加斯算法 .54【程序 11-2】 伪素数测试 .54【程序 11-3】 合数性检测 .55【程序 11-4】 素数测试的蒙特卡罗算法 .55【程序 11-5】 快速排序舍伍德算法 .56【程序 12-1】 平面图着色近似算法 .56【程序 12-2】 最小顶点覆盖近似算法 .56【程序 12-3】 集合覆盖近似算法 .56【程序 12-4】 子集和数算法 .57【程序 12-5】 修正表 L 为新表 57【程序 12-6】 子集和数近似方案 .571【程序 1
8、-1】 欧几里德递归算法void Swap(inta=b;b=c;int RGcd(int m,int n)if(m=0) return n;return RGcd(n%m,m);int Gcd(int m,int n)if (mn) Swap(m,n);return RGcd(m,n);【程序 1-2】 欧几里德迭代算法int Gcd(int m,int n)if (m=0)return n; if (n=0)return m;if (mn) Swap(m,n);while(m0)int c=n%m;n=m;m=c;return n;【程序 1-3】Gcd 的连续整数检测算法int Gcd(
9、int m,int n)if (m=0)return n;if (n=0)return m;int t=mn?n:m;while (m%t | n%t) t-;return t;【程序 1-4】 求 Fnlong Fib( long n)if(nvoid PrintDigit(unsigned int n) /设 k 位正整数为 d1d2d k, 按各位数的逆序 dkdk1d 1 形式输出cout=10) PrintDigit(n/10); /以逆序输出前 k-1 位数 void main()unsigned int n;cinn;PrintDigit(n);【程序 1-6】 汉诺塔问题#in
10、clude enum tower A=X, B=Y, C=Z;void Move(int n,tower x,tower y) /将第 n 个圆盘从塔座 x 移到塔座 y 的顶部cout void Perm(T a, int k, int n) if (k=n-1) /输出一种排列for (int i=0; ienum ResultCodeUnderflow, Overflow, Success, Duplicate, Fail, NotPresent;templatestruct BTNode/二叉树结点类BTNode(const T lChild=rChild=NULL;T element
11、;BTNode* lChild,*rChild;templateclass SPTree /伸展树类public:SPTree()root=NULL;ResultCode Insert(T x);protected:BTNode* root;private:ResultCode Insert(BTNode* void LRot(BTNode* void RRot(BTNode* ;【程序 3-2】 旋转函数template void SPTree:LRot(BTNode*p-rChild=r-lChild;r-lChild=p; p=r; /p 的右孩子成为子树根template void S
12、PTree:RRot(BTNode*5p-lChild=r-rChild;r-rChild=p;p=r; /p 的左孩子成为子树根【程序 3-3】 伸展树插入template ResultCode SPTree:Insert(T x)return Insert(root, x);template ResultCode SPTree:Insert(BTNode* BTNode* r;if (p=NULL) /插入新结点p=new BTNode(x); return result;if(x=p-element) result=Duplicate; return result;if (xelemen
13、t) r=p-lChild;if(r=NULL) /zig 旋转r=new BTNode(x); r-rChild=p; p=r;return result;else if(x=r-element) /zig 旋转RRot(p); result=Duplicate; return result;if(xelement) /zigzig 旋转result=Insert(r-lChild, x);RRot(p);else /zigzag 旋转result=Insert(r-rChild, x);LRot(r); p-lChild=r;RRot(p); 一个类上通过重载关系运算符或类型转换运算符,将
14、结构间的比较视为关键字间的比较。见附录 B。6else r=p-rChild;if(r=NULL) r=new BTNode(x); r-lChild=p; p=r; return result;else if(x=r-element) LRot(p); /zag 旋转result=Duplicate; return result;if(xr-element) /zagzag 旋转result=Insert(r-rChild, x);LRot(p);else /zagzig 旋转result=Insert(r-lChild, x);RRot(r); p-rChild=r;LRot(p);ret
15、urn result;【程序 3-4】 跳表结点类template struct SNodeSNode(int mSize)link=new SNode* mSize;SNode() delete link;T element;SNode*link;【程序 3-5】 跳表类templateclass SkipList 7public:SkipList(T large, int mLev); SkipList();ResultCode Insert(T x); /函数定义见 3.1.1 节private:int Level();SNode* SaveSearch(T x);int maxLeve
16、l, levels;SNode *head, *tail, *last;【程序 3-6】 构造函数template SkipList:SkipList(T large, int mLev)maxLevel=mLev; levels=0;head=new SNode(maxLevel+1); /指向包括元素域和 maxLevel+1 个指针的头结点tail=new SNode(0); /指向只有元素域,不包含指针域的尾结点last=new SNode*maxLevel+1; /maxLevel+1 个指针tail-element.key=large; /尾结点中保存作为哨兵值的最大值 large
17、for (int i=0; ilinki=tail; /头结点的所有指针指向尾结点【程序 3-7】 级数分配template int SkipList:Level()int lev=0;while (rand()SNode* SkipList:SaveSearch(T x) /假定 T 类已重载了关系运算符或类型转换运算符SNode*p=head;for(int i=levels; i=0; i-)8while(p-linki-element linki;lasti=p; /将最后搜索到的第 i 层结点的地址保存在 lasti中return (p-link0);template ResultC
18、ode SkipList:Insert(T x)if (x=tail-element) return RangeError;SNode* p=SaveSearch(x);if (p-element=x) return Duplicate; /表明有重复元素int lev=Level(); /计算级数if(levlevels)lev=+levels;lastlev=head;SNode* y=new SNode(lev+1); /构造新结点y-element=x;for(int i=0; ilinki=lasti-linki;lasti-linki=y;return Success;【程序 4-
19、1】 ENode 类enum ColorTypeWhite, Gray, Black;struct ENodeint adjVex;ENode* nextArc; class Graph public:Graph(int mSize) /构造仅有 n 个结点的图的邻接表n=mSize; a=new ENode* n;for (int i=0; i q(QSize);coloru=Gray; coutnextArc) /检测 E-结点 u 的全部邻接点int v=w-adjVex;if (colorv=White)colorv=Gray; coutnextArc)int v=w-adjVex;i
20、f (colorv=White) parentv=u;DFS(v, parent, color);coloru=Black; fu=time+; /记录第 2 个时间【程序 4-4】 计算 d 和 Lowvoid Graph:DFS(int u, int p)/u 是起始结点,p 是 u 的双亲结点Lowu=du=time+; /Lowu=dufor (ENode* w=au; w; w=w-nextArc)int v=w-adjVex;if (dv=-1) /表示 v 尚未访问DFS(v, u);if (LowuLowv) Lowu=Lowv; /是树边else if (v!=p eNode
21、 e;for (ENode* w=au; w; w=w-nextArc)int v=w-adjVex; e.u=u; e.v=v; if(v!=p else if(uv else if (v!=p 【程序 4-6】 与或树及其结点类型enum NTypeA, O, S, U; templatestruct TNodeTNode(const T tp=c;p=new TNode *d;for(int i=0; iclass AndOrTreepublic:AndOrTree(int degree);int Solvable()return PostOrder(root);12private:in
22、t PostOrder(TNode*t); /判定与或树是否可解TNode* root;int d;【程序 4-7】 判断与或树是否可解算法template int AndOrTree:PostOrder(TNode*t)int i;switch (t-tp)case S : return 1;case U : return 0;case A : for(i=0; ipi /有一个孩子不可解,返回 0return 1; /所有孩子均可解,返回 1default: for(i=0; ipi /有一个孩子可解,返回 1return 0; /所有孩子均不可解,返回 0【程序 4-8】 广度优先生成解
23、树的算法框架template int AndOrTree: BFTree(TNode t)/t 为树 T 的根结点,假定 t 有孩子Queue q(mSize); TNode v, x;q.EnQueue(t);dobool update=false;v=q.Front(); q.DeQueue();for( 对 v 的每个孩子 x ) /使用函数 f 生成 v 的所有孩子 xif (x 是分支结点) q.EnQueue(x); /x 是未定结点进队列else /叶结点不进队列if(x 是本原叶结点) 将 x 标记为可解;else 将 x 标记为不可解;update=true;生成结点 x 加
24、到解树 T 上作为 v 的孩子; 13if (update) /已遇到叶结点,需重新标记树 TSolvable(t); /重新标记树 T 中的结点从树 T 中删除所有标记为不可解的结点; /树中留下可解结点和未定结点if(t 为可解)return 1; /问题可解else if(t 为不可解) return 0; /问题不可解 从队列 q 中删除所有具有可解祖先的结点;从队列 q 中删除所有具有不可解祖先的结点;while(!q.IsEmpty();return 0; /问题不可解 【程序 5-1】 分治法SolutionType DandC(ProblemType P)ProblemType
25、 P1,P 2,P k;if (Small(P) return S(P); /子问题 P 足够小,用 S(P)直接求解else Divide(P,P 1,P 2,P k); /将问题 P 分解成子问题 P1, P2, , PkReturn Combine(DandC(P1),DandC(P 2),DandC(P k);/求解子问题,并合并解【程序 5-2】 一分为二的分治法SolutionType DandC(int left,int right)if (Small(left,right) return S(left,right);else int m=Divide(left,right);
26、/以 m 为界将问题分解成两个子问题Return Combine(DandC(left,m),DandC(m+1 ,right); /分别求解子问题,并合并解【程序 5-3】 可排序表类template struct E /可排序表中元素的类型operator K()const return key; /重载类型转换运算符K key; /关键字可以比较大小D data; /其他数据14;template class SortableList /可排序表类public:SortableList(int mSize) /构造函数 maxSize=mSize;l=new TmaxSize;n=0;S
27、ortableList()delete l; /析构函数private:T *l ; /动态生成一维数组int maxSize; /线性表的最大表长int n; /线性表的实际长度;【程序 5-4】 求最大最小元template void SortableList:MaxMin(Tmax=min=l0; for (int i=1; imax) max=li; if(livoid SortableList:MaxMin(int i, int j, Tif (i=j) max=min=li; /表中只有一个元素时else if (i=j-1) /表中有两个元素时if (limin1) min=mi
28、n1; /两子表最小元的小者为原表最小元 【程序 5-6】 二分搜索算法框架template int SortableList:BSearch(const Telse return m; /搜索成功return -1; /搜索失败 【程序 5-7】 对半搜索递归算法template int SortableList:BSearch(const T /搜索右半子表else return m; /搜索成功return-1; /搜索失败【程序 5-8】 对半搜索的迭代算法template 16int SortableList:BSearch1(const Twhile (leftlm) left=m
29、+1;else return m; /搜索成功return-1; /搜索失败【程序 5-9】 Merge 函数template void SortableList:Merge(int left, int mid, int right) T* temp=new Tright-left+1;int i=left, j=mid+1, k=0;while ( ivoid SortableList:MergeSort()MergeSort(0, n-1);template void SortableList:MergeSort(int left, int right)if (leftint Sortab
30、leList:Partition(int left, int right) /前置条件:left Arightint i=left, j=right+1;do do i+; while (lilleft);if (ivoid SortableList:QuickSort()QuickSort(0, n-1);template void SortableList:QuickSort(int left, int right)if(leftResultCode SortableList:Select1(Tif (nclass Knapsack public:Knapsack(int mSize, f
31、loat cap, float *wei, T *prof); /创建一维数组 w 和 p,并赋初值void GreedyKnapsack(float* x); /数组 x 为背包问题的最优解private:float m, *w; /m 为背包载重量,w 指示存储 n 个物品重量的数组T *p; /p 指示存储 n 个物品收益的数组int n; /n 为物品数目;templatevoid Knapsack:GreedyKnapsack(float* x)/前置条件:wi已按 pi/wi的非增次序排列float u=m; /u 为背包剩余载重量,初始时为 mfor (int i=0; iu)
32、break;xi=1.0;u=uwi;if (i=0 /搜索作业 j 的插入位置if(rr+1) /若条件不满足,选下一个作业for (int i=k; i=r+1; i-) xi+1=xi; /将 xr以后的作业后移xr+1=j; k+; /将作业 j 插入 r+1 处return k;【程序 6-5】 使用并查集的带时限作业排序程序int FJS(int *d, int *x, int n) UFSet s(n); /创建由 n 棵树组成的并查集实例 sint b, k=-1, *f=new intn+1;for (int i=0; istruct HNode/优先权队列中元素的类型ope
33、rator T()const return weight;BTNode *ptr;T weight;template BTNode* CreateHfmTree (T* w, int n) 21/w 为一维数组保存 n 个权值PrioQueue pq(2*n-1); /创建长度为 2n-1 的优先权队列实例 pqBTNode*p; HNode a, b; /定义局部变量for (int i=0; i(wi); /创建一个合并树的新结点a.ptr=p; a.weight=wi; /对象 a 包含指向根的指针和根的权值pq.Append(a) /将指向根的指针和根的权值进队列 pqfor (i=1
34、; i(a.weight, a.ptr, b.ptr); /将取出的两棵树合并,构造一棵新二叉树a.ptr=p;pq.Append(a); /将指向新根的指针和根的权值进队列 pqpq.Serve(a); /取出生成的最佳合并树return a.ptr; /a.ptr 指向最佳合并树的根【程序 6-7】 最小代价生成树的贪心算法ESetType SpanningTree(ESetType E, int n) /G=(V, E)为无向图,E 是图 G 的边集,n 是图中结点数ESetType S=; /S 为生成树上边的集合int u, v, k=0; EType e; /e = (u, v)为
35、一条边while (kstruct ENode/带权图的边结点int adjVex;T w;ENode* nextArc;22template class Graphpublic:Graph (int mSize);void Prim(int s);protected:void Prim(int k, int* nearest, T* lowcost);ENode* a;int n; ;templatevoid Graph:Prim(int s)/公有成员函数int* nearest=new intn, *lowcost=new intn;Prim(s, nearest, lowcost);f
36、or(int j=0; jvoid Graph:Prim(int k, int* nearest, T* lowcost)/私有成员函数bool* mark=new booln; /创建 mark 数组ENode *p;if (kn-1) throw OutofBounds;for (int i=0; inextArc) /修改 lowcost 和 nearest 的值int j= p-adjVex;if (!markj ) nearestj=k;23T min=INFTY; /求下一条最小权值的边for (int j=0; jvoid Graph:Kruskal(PrioQueue UFSe
37、t s(n); /建立一个并查集 sint u, v, k=0; while (kclass MGraph public:MGraph(int mSize);void Dijkstra(int s, T*private:int Choose(int* d, bool* s); /在一维数组 d 中求最小值24T*a; /动态生成二维数组 a,存储图的邻接矩阵int n; /图中顶点数;template int MGraph:Choose(int* d, bool* s)int i, minpos; T min;min=INFTY; minpos=-1;for (i=1; ivoid MGrap
38、h:Dijkstra(int s, T*if (sn-1) throw OutOfBounds;bool *inS=new booln; d=new Tn; path=new intn;for (i=0; ivoid Store(int n, int m) 25int j = 0; for (int i=0; iT Graph:FMultiGraph(int k, int *p)/采用程序 6-8 的邻接表存储图 GTc,*cost=new floatn; int q, *d=new intn;costn-1=0, dn-1= -1; /设置向前递推的初值for (int j=n-2; j=0
39、; j-) /按 n-2, , 0 的次序计算 cost 和 dfloat min=INFTY; /按式(7-1)计算最小值为 costjfor (ENode *r=aj; r; r=r-nextArc) int v=r-adjVex;if (r-w+costvw+costv; q=v;costj=min; dj=q; /q 是 j 在最短子路径上的后继结点p0=0; pk-1=n-1; c=cost0; /p0和 pn-1是源点和汇点for(j=1; jvoid MGraph:Floyd(T*d= new T*n; path=new int *n;for(i=0; in; i+)di=new
40、 T n; pathi=new intn;for (j=0; jn; j+) /初始化dij=aij;26if (i!=j else pathij= -1;for (k=0; kn; k+) /考察结点 kfor (i=0; in; i+)for (j=0; jn; j+) if (dik+dkj dij )dij=dik+dkj;pathij=pathkj;【程序 7-3】 矩阵连乘算法class MatrixChainpublic:MatrixChain(int mSize, int *q); /创建二维数组 m 和 s,一维数组 p,并初始化int MChain(); /一般动态规划法求
41、最优解值int LookupChain(); /备忘录方法求最优解值(程序 7-4)void Traceback(); /构造最优解的公有函数private:void Traceback(int i, int j); /构造最优解的私有递归函数int LookupChain(int i, int j); /备忘录方法私有递归(程序 7-4)int *p, *m, *s, n;int MatrixChain:MChain() /求 A0:n-1的最优解值for (int i=0;in; i+) mii=0;for (int r=2; r=n; r+)for (int i=0; i=n-r; i+) int j=i+r-1;mij=mi+1j+pi*pi+1*pj+1; /mij 的初值sij=i;for (int k=i+1; kj; k+) int t=mik+mk+1j+pi*pk+1*pj+1;if (tmij) mij=t; sij=k;