最小生成树

最小生成树的各种算法
子图:从原图中选中一些顶点和边组成的图.

生成子图:选中一些边和所有顶点组成的图.

生成树:正好是一棵树的生成子图.

最小生成树:权值之和最小的生成树.
Prim算法

复杂度:O(n^2) $$

$$

#include
using namespace std;
const int INF = 1e4;
const int N = 100;
bool s[N];
int closest[N]; //存储U集合中离U-V集合中最近的点
int lowcost[N]; //最近点间的距离
void Prim(int n,int u0,int c[N][N])
{
s[u0]=true; //初始值在U集合中
int i,j;
for(i=1;i<=n;i++) //初始化lowcost和closest数组
{
if(i!=u0)
{
lowcost[i]=c[u0][i];
closest[i]=u0;
s[i]=false;
}
else
lowcost[i]=0;
}
for(i=1;i<=n;i++)
{
int temp = INF;
int t=u0;
for(j=1;j<=n;j++) //在集合U-V中找到离集合U中最近的点
{
if(!s[j]&&(lowcost[j]<temp))
{
t=j;
temp=lowcost[j];
}
}
if(t==u0)
break;
s[t]=true;
for(j=1;j<=n;j++) //更新closest和lowcost数组
{
if(!s[j]&&(c[t][j]<lowcost[j]))
{
lowcost[j]=c[t][j];
closest[j]=t;
}
}
}
}
int main()
{
int n,c[N][N],m,u,v,w;
int u0;
cout<<“请输入节点数n和边数m:”<<endl;
cin>>n>>m;
int sumcost=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
c[i][j]=INF;
cout<<“输入节点数u,v和边值w:”<<endl;
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
c[u][v]=c[v][u]=w;
}
cout<<“输入任一节点u0:”<<endl;
cin>>u0;
Prim(n,u0,c);
cout<<“数组lowcost的内容为:”<<endl;
for(int i=1;i<=n;i++)
{
cout<<lowcost[i]<<" ";
sumcost+=lowcost[i];
}
cout<<endl;
cout<<“最小的花费是:”<<sumcost<<endl;
}

Kruskal算法

复杂度:O(e*logn)

#include
#include
#include
using namespace std;
const int N = 100;
int nodeset[N];
int n,m;
struct Edge{
int u;
int v;
int w;
}e[N*N]; //边集
bool cmp(Edge x,Edge y)
{
return x.w<y.w;
}
void Init(int n) //初始化点集,每个点为一个集合
{
for(int i =1;i<=n;i++)
nodeset[i]=i;
}
int Merge(int a,int b) //避圈法,若线的两端在同一点集里,则会产生回路,应避免
{
int p=nodeset[a];
int q=nodeset[b];
if(p==q)
return 0;
for(int i=1;i<=n;i++) //将所有连接在一起的点构成同一点集
{
if(nodeset[i]q)
nodeset[i]=p;
}
return 1;
}
int Kurskal(int n)
{
int ans=0;
for(int i=0;i<m;i++)
if(Merge(e[i].u,e[i].v))
{
ans+=e[i].w;
n–;
if(n
1)
return ans;
}
return 0;
}
int main()
{
cout<<“输入节点数n和边数m:”<<endl;
cin>>n>>m;
Init(n);
cout<<“输入节点数u,v和边值w:”<<endl;
for(int i=1;i<=m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e,e+m,cmp);
int ans=Kurskal(n);
cout<<“最小花费是:”<<ans<<endl;
return 0;
}

并查集改进的Kruskal算法

复杂度:O(n^2) $$

$$

#include
#include
#include
using namespace std;
const int N = 100;
int father[N];
int n,m;
struct Edge{
int u;
int v;
int w;
}e[N*N];
bool cmp(Edge x,Edge y)
{
return x.w<y.w;
}
void Init(int n)
{
for(int i =1;i<=n;i++)
father[i]=i;
}
int Find(int x)
{
if(x!=father[x])
father[x]=Find(father[x]);
return father[x];
}
int Merge(int a,int b)
{
int p = Find(a);
int q = Find(b);
if(pq)
return 0;
if(p>q)
father[p]=q;
else
father[q]=p;
return 1;
}
int Kurskal(int n)
{
int ans=0;
for(int i=0;i<m;i++)
if(Merge(e[i].u,e[i].v))
{
ans+=e[i].w;
n–;
if(n
1)
return ans;
}
return 0;
}
int main()
{
cout<<“输入节点数n和边数m:”<<endl;
cin>>n>>m;
Init(n);
cout<<“输入节点数u,v和边值w:”<<endl;
for(int i=1;i<=m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e,e+m,cmp);
int ans=Kurskal(n);
cout<<“最小花费是:”<<ans<<endl;
return 0;
}

分治法

二分搜索

循环搜索

#include
#include
#include
#include
using namespace std;
const int M=100;
int x,n,i;
int s[M];
int BinarySearch(int n,int s[],int x)
{
int low=0,high=n-1,middle;
while(low<=high)
{
middle=(low+high)/2;
if(xs[middle])
return middle;
else if(x<s[middle])
high=middle-1;
else
low=middle+1;
}
return -1;
}
int main()
{
cout<<“输入数列元素个数n:”<<endl;
while(cin>>n)
{
cout<<“依次输入数列元素:”<<endl;
for(i=0;i<n;i++)
cin>>s[i];
sort(s,s+n);
cout<<“排序后的数组:”<<endl;
for(i=0;i<n;i++)
cout<<s[i]<<" ";
cout<<endl;
cout<<“输入要查找的元素:”<<endl;
cin>>x;
i=BinarySearch(n,s,x);
if(i
-1)
cout<<“没有查找到”<<endl;
else
cout<<“查找的元素在第”<<i+1<<“位”<<endl;
}
return 0;
}

递归搜索

int recursionBS(int s[],int x,int low,int high)
{
if(low>high)
return -1;
int middle=(low+high)/2;
if(x==s[middle])
return middle;
else if(s<s[middle])
return recursionBS(s,x,low,middle-1);
else
return recursionBS(s,x,middle+1,high);
}

合并排序

#include
#include
#include
//#include
using namespace std;
void Merge(int A[],int low,int mid,int high)
{
int *B=new int[high-low+1];
int i=low,j=mid+1,k=0;
while(i<=mid&&j<=high)
{
if(A[i]<=A[j])
B[k++]=A[i++];
else
B[k++]=A[j++];
}
while(i<=mid)
B[k++]=A[i++];
while(j<=high)
B[k++]=A[j++];
for(i=low,k=0;i<=high;i++)
A[i]=B[k++];
}
void MergeSort(int A[],int low,int high)
{
if(low<high)
{
int mid=(low+high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,high);
}
}
int main()
{
int n,A[100];
cout<<“输入元素个数:”<<endl;
cin>>n;
cout<<“输入每个元素:”<<endl;
for(int i=0;i<n;i++)
cin>>A[i];
MergeSort(A,0,n-1);
cout<<“合并排序结果为:”<<endl;
for(int i=0;i<n;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}

快速排序

原始

#include
using namespace std;
int Partition(int r[],int low,int high)
{
int i=low,j=high,pivot=r[low];
while(i<j)
{
while(i<j&&r[j]>pivot) j–;
if(i<j)
swap(r[i++],r[j]);
while(i<j&&r[i]<=pivot) i++;
if(i<j)
swap(r[i],r[j–]);
}
return i;
}
void QuickSort(int r[],int low,int high)
{
int mid;
if(low<high)
{
mid=Partition(r,low,high);
QuickSort(r,low,mid-1);
QuickSort(r,mid+1,high);
}
}
int main()
{
int n,A[100];
cout<<“输入元素个数:”<<endl;
cin>>n;
cout<<“输入每个元素:”<<endl;
for(int i=0;i<n;i++)
cin>>A[i];
QuickSort(A,0,n-1);
cout<<“快速排序结果为:”<<endl;
for(int i=0;i<n;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}

改进

可减少交换次数,提高效率

int Partition2(int r[],int low,int high)
{
int i=low,j=high,pivot=r[low];
while(i<j)
{
while(i<j&&r[j]>pivot)
j–;
while(i<j&&r[i]<=pivot)
i++;
if(i<j)
swap(r[i++],r[j–]);
}
if(r[i]>pivot)
{
swap(r[i-1],r[low]);
return i-1;
}
swap(r[i],r[low]);
return i;
}

大整数乘法

#include
#include
#include<stdio.h>
using namespace std;
#define M 100
char sa[100],sb[100];
typedef struct _Node
{
int s[M];
int l;
int c;
}Node,pNode;
void cp(pNode src,pNode des,int st,int l) //拆分函数,st为起点
{
int i,j;
for(i=st,j=0;i<st+l;i++,j++)
des->s[j]=src->s[i];
des->l=l;
des->c=st+src->c;
}
void add(pNode pa,pNode pb,pNode ans)
{
int i,cc,k,palen,pblen,len;
int ta,tb;
pNode temp;
if((pa->c)<(pb->c)) //保证幂指数较大的为pa
{
temp=pa;
pa=pb;
pb=temp;
}
ans->c=pb->c; //结果的幂指数等于较小的幂指数
cc=0; //进位初始为0
palen=pa->l+pa->c;
pblen=pb->l+pb->c;
if(palen<pblen)
len=pblen;
else
len=palen; //总的长度为最长的那一个
k=pa->c-pb->c; //pa需要补充的0的个数
for(i=0;ic;i++)
{
if(i<k) //pa的前k位都是补充的0
ta=0;
else
ta=pa->s[i-k];
if(i< pb->l)
tb=pb->s[i];
else //超过pb长度的位pb的值都是0
tb=0;
if(i>=pa->l+k) //超过pa长度的位pa的值都是0
ta=0;
ans->s[i]=(ta+tb+cc)%10;
cc=(ta+tb+cc)/10;
}
if(cc)
ans->s[i++]=cc;
ans->l=i;
}
void mul(pNode pa,pNode pb,pNode ans)
{
int i,cc,w;
int ma=pa->l>>1,mb=pb->l>>1;
Node ah,al,bh,bl;
Node t1,t2,t3,t4,z;
pNode temp;
if(!ma||!mb) //当pa或pb有一个只有1位时开始乘法
{
if(!ma) //保证pa为较大值
{
temp=pa;
pa=pb;
pb=temp;
}
ans->c=pa->c+pb->c; //结果的幂指数=两个乘数的幂指数之和
w=pb->s[0]; //pb只有1位,用常数表示
cc=0;
for(i=0;il;i++)
{
ans->s[i]=(w
pa->s[i]+cc)%10;
cc=(w*pa->s[i]+cc)/10;
}
if(cc)
ans->s[i++]=cc; //最后的进位填进数组最后
ans->l=i;
return;
}
cp(pa,&ah,ma,pa->l-ma);
cp(pa,&al,0,ma);
cp(pb,&bh,mb,pb->l-mb);
cp(pb,&bl,0,mb);

mul(&ah,&bh,&t1);
mul(&ah,&bl,&t2);
mul(&al,&bh,&t3);
mul(&al,&bl,&t4);

add(&t3,&t4,ans);
add(&t2,ans,&z);
add(&t1,&z,ans);

}
int main()
{
Node ans,a,b;
cout<<“输入大数1:”<<endl;
cin>>sa;
cout<<“输入大数2:”<<endl;
cin>>sb;
a.l=strlen(sa);
b.l=strlen(sb);
int z=0,i;
for(i=a.l-1;i>=0;i–) //把输入的字符转为数字并倒序存入数组
a.s[z++]=sa[i]-‘0’;
a.c=0;
z=0;
for(i=b.l-1;i>=0;i–)
b.s[z++]=sb[i]-‘0’;
b.c=0;
mul(&a,&b,&ans);
cout<<“结果为:”<<endl;
for(i=ans.l-1;i>=0;i–)
cout<<ans.s[i];
cout<<endl;
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值