完整word版,新算法⼤全(C,C++),推荐⽂档算法⼤全(C,C++)
⼀、数论算法
1.求两数的最⼤公约数
function gcd(a,b:integer):integer;
begin
if b=0 then gcd:=a
else gcd:=gcd (b,a mod b);
end ;
2.求两数的最⼩公倍数
function lcm(a,b:integer):integer;
begin
if a
lcm:=a;
while lcm mod b>0 do inc(lcm,a);
end;
3.素数的求法
A.⼩范围内判断⼀个数是否为质数:
function prime (n: integer): Boolean;
var I: integer;
begin
for I:=2 to trunc(sqrt(n)) do
if n mod I=0 then begin
prime:=false; exit;
end;
prime:=true;
end;
B.判断longint范围内的数是否为素数(包含求50000以内的素数表):procedure getprime; var
i,j:longint;
p:array[1..50000] of boolean;
begin
fillchar(p,sizeof(p),true);
p[1]:=false;
i:=2;
while i<50000 do begin
if p[i] then begin
j:=i*2;
while j<50000 do begin
p[j]:=false;
end;
end;
inc(i);
end;
l:=0;
for i:=1 to 50000 do
if p[i] then begin
inc(l);pr[l]:=i;
end;
end;{getprime}
function prime(x:longint):integer;
var i:integer;
begin
prime:=false;
for i:=1 to l do
if pr[i]>=x then break
else if x mod pr[i]=0 then exit;
prime:=true;
end;{prime}
⼆、图论算法
1.最⼩⽣成树
A.Prim算法:
procedure prim(v0:integer);
var
lowcost,closest:axn] of integer; i,j,k,min:integer;
begin
for i:=1 to n do begin
lowcost[i]:=cost[v0,i];
closest[i]:=v0;
end;
for i:=1 to n-1 do begin
{寻离⽣成树最近的未加⼊顶点k}
min:=maxlongint;
for j:=1 to n do
if (lowcost[j]0) then begin min:=lowcost[j];
end;
lowcost[k]:=0; {将顶点k加⼊⽣成树}
{⽣成树中增加⼀条新的边k到closest[k]}
{修正各点的lowcost和closest值}
for j:=1 to n do
if cost[k,j]
lowcost[j]:=cost[k,j];
closest[j]:=k;
end;
end;
end;{prim}
B.Kruskal算法:(贪⼼)
按权值递增顺序删去图中的边,若不形成回路则将此边加⼊最⼩⽣成树。
function find(v:integer):integer; {返回顶点v所在的集合}
var i:integer;
begin
i:=1;
while (i<=n) and (not v in vset[i]) do inc(i);
if i<=n then find:=i else find:=0;
end;
procedure kruskal;
var
tot,i,j:integer;
typec转dpbegin
for i:=1 to n do vset[i]:=[i];{初始化定义n个集合,第I个集合包含⼀个元素I}
p:=n-1; q:=1; tot:=0; {p为尚待加⼊的边数,q为边集指针}
sort;
{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度} while p>0 do begin
i:=find(e[q].v1);j:=find(e[q].v2);
if i<>j then begin
inc(tot,e[q].len);
vset[i]:=vset[i]+vset[j];vset[j]:=[];
dec(p);
end;
inc(q);
end;
writeln(tot);
end;
2.最短路径
A.标号法求解单源点最短路径:
var
a:axn] of integer;
b:axn] of integer; {b[i]指顶点i到源点的最短路径} mark:axn] of boolean;
procedure bhf;
var
best,best_j:integer;
begin
fillchar(mark,sizeof(mark),false);
mark[1]:=true; b[1]:=0;{1为源点}
repeat
best:=0;
for i:=1 to n do
If mark[i] then {对每⼀个已计算出最短路径的点}
for j:=1 to n do
if (not mark[j]) and (a[i,j]>0) then
if (best=0) or (b[i]+a[i,j]
best:=b[i]+a[i,j]; best_j:=j;
end;
if best>0 then begin
b[best_j]:=best;mark[best_j]:=true;
end;
until best=0;
end;{bhf}
B.Floyed算法求解所有顶点对之间的最短路径:
procedure floyed;
begin
for I:=1 to n do
for j:=1 to n do
if a[I,j]>0 then p[I,j]:=I else p[I,j]:=0; {p[I,j]表⽰I到j的最短路径上j的前驱结点} for k:=1 to n do {枚举中间结点}
for i:=1 to n do
for j:=1 to n do
if a[i,k]+a[j,k]
a[i,j]:=a[i,k]+a[k,j];
p[I,j]:=p[k,j];
end;
end;
C. Dijkstra 算法:
var
a:axn] of integer;
b,pre:axn] of integer; {pre[i]指最短路径上I的前驱结点} mark:axn] of boolean;
procedure dijkstra(v0:integer);
begin
fillchar(mark,sizeof(mark),false);
for i:=1 to n do begin
d[i]:=a[v0,i];
if d[i]<>0 then pre[i]:=v0 else pre[i]:=0;
end;
mark[v0]:=true;
repeat {每循环⼀次加⼊⼀个离1集合最近的结点并调整其他结点的参数} min:=maxint; u:=0; {u记录离1集合最近的结点}
for i:=1 to n do
if (not mark[i]) and (d[i]
u:=i; min:=d[i];
end;
if u<>0 then begin
mark[u]:=true;
for i:=1 to n do
if (not mark[i]) and (a[u,i]+d[u]
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论