//本算法未采用生成树,只用输出表示找到了,prime 与kluskal 对于同一个没有相同相同权值图应该一样,即使不一样所有最小生成树权值和应该一样
#include <iostream>
#include<time.h>
#include<math.h>
using namespace std;
#define random(x) (rand()%x)
#define VertexType char
#define MaxVertexNum 1000
typedef struct node{
int adjvex; //邻接点域
struct node *next; //链域
bool visited;//若欧拉图用其表示边是否遍历,边排序时也用到
int weight;//若要表示边上的权,则应增加一个数据域
}EdgeNode; //边表结点
typedef struct vnode{
VertexType vertex; //顶点域
EdgeNode *firstedge;//边表头指针
bool visited;//表示点是否遍历,若欧拉图用其表示边是否遍历
}VertexNode; //顶点表结点
typedef VertexNode AdjList[MaxVertexNum];//AdjList是邻接表类型
typedef struct{
AdjList adjlist;//邻接表
int n,e; //图中当前顶点数和边数
}ALGraph;
typedef struct edgenode{//存放边排序
int left,right;
int weight;
}edge;
typedef edge edge_arr[MaxVertexNum];
edge_arr array;
ALGraph G;
void AddEdge(int i,int j,int weight)
{
EdgeNode *s;
s=(EdgeNode *)malloc(sizeof(EdgeNode)); //生成边表结点
s->adjvex=j;//邻接点序号为randint
s->visited=false;
s->next=G.adjlist[i].firstedge;
s->weight=weight;
G.adjlist[i].firstedge=s; //将新结点*s插入顶点vi的边表头部
s=(EdgeNode *)malloc(sizeof(EdgeNode));
s->adjvex=i; //邻接点序号为i
s->visited=false;
s->next=G.adjlist[j].firstedge;
s->weight=weight;
G.adjlist[j].firstedge=s; //将新结点*s插入顶点Vrandint的边表头部
}
int GetNodeDegree(int i)
{
EdgeNode *s;
int degree=0;
for(s=G.adjlist[i].firstedge;s!=NULL;s=s->next)
{
degree++;
}
return degree;
}
void CreateConnectedGraph(ALGraph *G)
{
int i,j,k;
//EdgeNode *s,*edgetmp;
EdgeNode *edgetmp;
//srand((unsigned int)time(0));//获取系统当前时间
printf("please input the number of the vertex:\n");
scanf("%d",&G->n);
G->e=0;
char c='A';
for(i=0;i<G->n;i++)
{ //建立顶点表
G->adjlist[i].vertex=c;c++; //读入顶点信息 A,B.C.D.E
G->adjlist[i].firstedge=NULL;//边表置为空表
G->adjlist[i].visited=false;//
}
for(i=0;i<G->n;i++)
{
cout<<G->adjlist[i].vertex<<" ";
}
cout<<endl;
//////生成随即连通图
//先 生成树//后添加n条边
for(i=0;i<G->n;i++)
{
if(GetNodeDegree(i)==G->n-1)
{
continue;
}//某一点已与其余各个顶点相连接
bool flag=false;
int randint=random(G->n);//随机找到一顶点,不是该结点本身
while(randint==i)
{
randint=random(G->n);
}
for(edgetmp=G->adjlist[i].firstedge;edgetmp!=NULL;edgetmp=edgetmp->next)
{
if(edgetmp->adjvex==randint)///////新边已经存在
{
flag=true;
i--;//?
break;
}
}///End for
if(flag)
{
continue;
}
else
{
AddEdge(i,randint,random(100));//weight arnge from 1 to 100
G->e++;
//cout<<endl<<"in 生成树 have inserted a edge between "<<i<<" and "<<randint<<endl;
}
}////End 生成树
for(j=0;j<G->n;j++)
{
int randint1=random(G->n);
//randint1=j;
int randint2=random(G->n);
while(randint1==randint2)
{
randint2=random(G->n);
}
//AddEdge(randint1,randint2,random(100));
//G->e++;
//cout<<"生成树后 randint1 is "<<randint1<<" randint2 is "<<randint2<<endl;
bool flag2=false;
for(edgetmp=G->adjlist[randint1].firstedge;edgetmp!=NULL;edgetmp=edgetmp->next)
{
if(edgetmp->adjvex==randint2)///////新边已经存在
{
flag2=true;
//j--;
break;
}
}///End for
if(flag2)
{
continue;
}
else
{
AddEdge(randint1,randint2,random(100));//weight arnge from 1 to 100
G->e++;
//cout<<endl<<"in 后加入边 have inserted a edge between "<<randint1<<" and "<<randint2<<endl;
}
}
}
void DFS(ALGraph &G,int i)
{
EdgeNode *p;
//for(int i=0;i<G.n;i++)
//{
if(G.adjlist[i].visited==false)
{
cout<<G.adjlist[i].vertex<<" ";//便利当前顶点
G.adjlist[i].visited=true;
}
for(p=G.adjlist[i].firstedge;p!=NULL;p=p->next)
{
if(G.adjlist[p->adjvex].visited==false)
DFS(G,p->adjvex);
}
//}
}
void morge(edge_arr &array,int low,int mid,int high)
{
edge *temp= new edge [high-low+1];//边 结构体数组
int i=low;
int j=mid+1;
//temp={0};
int k=0;
while(i<=mid&&j<=high)
{
if(array[i].weight>array[j].weight)
{
temp[k].weight=array[j].weight;
temp[k].left=array[j].left;
temp[k].right=array[j].right;
j++;
}
else {
temp[k].weight=array[i].weight;
temp[k].left=array[i].left;
temp[k].right=array[i].right;
i++;
}
k++;
}
while(i<=mid)
{
temp[k].weight=array[i].weight;
temp[k].left=array[i].left;
temp[k].right=array[i].right;
k++;i++;
}
while(j<=high)
{
temp[k].weight=array[j].weight;
temp[k].left=array[j].left;
temp[k].right=array[j].right;
j++;k++;
}
for(i=low,j=0;i<=high;i++,j++)
{
array[i].weight=temp[j].weight;
array[i].left=temp[j].left;
array[i].right=temp[j].right;
}
}
void morge_sort(edge_arr &array,int low,int high)
{
if(low<high)
{
int mid=(low+high)/2;
morge_sort(array,low,mid);
morge_sort(array,mid+1,high);
morge(array,low,mid,high);
}
}
void sort_edge(ALGraph &G,edge_arr &array,int n)//用归并排序排序边array带回返回值,要做的是把图中的边放到array中,
//应放三个域,左起节点,右起节点,和权值,在从图中取出一边后,应删除对应的另一条边,
//用邻接矩阵存储比较方便,再次还要建立邻接矩阵用于标记是否当前边被删过,不可以 初始化时间复杂度就已经n的平方了,
{
EdgeNode *p,*q;// 应在边结构体中加一个visited用于变的遍历,创建时初始化false
// int arr=new int[G.e+1];
int k=0;
for(int i=0;i<G.n;i++)
for(p=G.adjlist[i].firstedge;p!=NULL;p=p->next)//,
{
if(p->visited==false)
{
array[k].left=i;
array[k].right=p->adjvex;
array[k].weight=p->weight;
p->visited=true;
q=G.adjlist[p->adjvex].firstedge;//对应边
while(q!=NULL&&q->adjvex!=i)q=q->next;
if(q!=NULL)q->visited=true;
k++;
}
}
//for(i=0;i<G.e;i++)
//cout<<"before sort"<<endl<<" left node is "<<array[i].left<<" weight is "<<array[i].weight<<" right node is "<<array[i].right<<endl;
morge_sort(array,0,G.e-1);
}
void cluskar(ALGraph &G)
{
int r1,r2,ro1,ro2,k=0,ij=0;
int *root=new int [G.n];//正数表示当前节点的根节点,零也是。负数表示以其为根节点的字数总节点数,本身自己就是根节点
for(int i=0;i<G.n;i++)
root[i]=-1;
sort_edge(G,array,G.n);
//for(i=0;i<G.e;i++)
//cout<<endl<<" left node is "<<array[i].left<<" weight is "<<array[i].weight<<" right node is "<<array[i].right<<endl;
for(int j=0;j<G.e-1;j++)//
{
r1=array[k].left;
r2=array[k].right;
cout<<endl<<" in cluskar test "<<array[k].left<<" "<<array[k].weight<<" "<<array[k].right<<endl;
if(root[r1]<0)ro1=r1;//当前节点本身 r1是跟节点,其绝对值是子树节点总数。否则root[r1] 是根节点
else ro1=root[r1];
if(root[r2]<0)ro2=r2;//当前节点本身 r1是跟节点,其绝对值是子树节点总数。否则root[r1] 是根节点
else ro2=root[r2];
if(ro1!=ro2)//不在同一个跟下
{
//cout<<"r1 is "<<r1<<" r2 is "<<r2<<endl;
//cout<<"ro1 is "<<ro1<<" ro2 is "<<ro2<<endl;
//cout<<endl<<" in cluskar "<<array[k].left<<" "<<array[k].weight<<" "<<array[k].right<<endl;
//for(int m=0;m<G.n;m++)cout<<" "<<m<<"//"<<root[m]<<" ";
//cout<<endl;
if(abs(root[ro1])>=abs(root[ro2]))//此时root1[ro1]里的数应该是负数,因为找到的是跟。
{
root[ro1]=root[ro1]+root[ro2];
//原来root【2】是负数,存放的是是根节点,当其作为子树时,以其为根的所有子节点的父节点都应作调整
for(int m=0;m<G.n;m++)//? 时间复杂度??????????????
if(root[m]>=0&&root[m]==ro2)//仅当root【】大于0时才表示根节点
root[m]=ro1;//新的根节点
root[ro2]=ro1;//此句应后执行,此时root[ro2]放的是根节点编号
}
else
{
root[ro2]=root[ro1]+root[ro2];
for(int m=0;m<G.n;m++)//? 时间复杂度??????????????
if(root[m]>=0&&root[m]==ro1)
root[m]=ro2;//新的根节点
root[ro1]=ro2;//此时root[ro1]放的是根节点编号
}
//cout<<"调后"<<endl;
//for(m=0;m<G.n;m++)cout<<" "<<m<<"//"<<root[m]<<" ";
ij++;
if(ij==G.n-1)break;
}
k++;
}
}
int smallest(int *lowcost,int *flag,int n)
{
int k=0;
while(flag[k]!=0){k++;}//找第一个flag=0作为初始时的最小花费位置
for(int i=k;i<n;i++)
{
if(flag[i]==0)
{
if(lowcost[k]>lowcost[i])k=i;
//cout<<"in test in smallest k is "<<k<<" j is "<<i<<endl;
}
}
//cout<<"in find smallest "<<k<<endl;
return k;
}
void prim(ALGraph &G)//从0点开始
{
int *adjv= new int[G.n];
int *lowcost = new int[G.n];
int *flag=new int[G.n];
EdgeNode *p;
for(int i=1;i<G.n;i++)
{
flag[i]=0;
lowcost[i]=1000;
adjv[i]=0;
}
flag[0]=1;
int ki=0;
int k=0;//k表示当前节点,ki表示与k相连的节点
for(p=G.adjlist[0].firstedge;p!=NULL;p=p->next)//,
{
lowcost[p->adjvex]=p->weight;//ki++;
}
int kj;
for(int j=0;j<G.n-1;j++)//还有n-1个顶点
{
kj=smallest(lowcost,flag,G.n);//kj表示找到的到其最小距离的点
//cout<<"in test in for kj is "<<kj<<endl;
if(flag[kj]==0)
{
flag[kj]=1;
for(p=G.adjlist[kj].firstedge;p!=NULL;p=p->next)//,
{
if(flag[p->adjvex]==0)
{
if(lowcost[p->adjvex]>p->weight)
{
//cout<<"in test in if lowcost "<<lowcost[p->adjvex]<<endl;
lowcost[p->adjvex]=p->weight;
adjv[p->adjvex]=kj;//p->adjvex 通过kj达到最小元素
//cout<<"in test in if lowcost "<<lowcost[p->adjvex]<<endl;
}
}
}
//
}
//else
//ki=kj;
}
for(int ij=1;ij<G.n;ij++)
cout<<endl<<" prime leftnode "<<adjv[ij]<<" rightnode "<<ij<<endl;
}
int main()
{
CreateConnectedGraph(&G);
cout<<"current graph vex number is "<<G.n<<endl;
cout<<"current graph edge number is "<<G.e<<endl;
DFS(G,0);
//sort_edge(G,array,G.n);//
prim(G);
cluskar(G);
//对于10,11,12数目节点不一样
//有错误,对于不存在权值相同的连通图因该是一样的
cout<<"grape as follow :"<<endl;
for(int i=0;i<G.e;i++)//
cout<<endl<<" left node is "<<array[i].left<<" weight is "<<array[i].weight<<" right node is "<<array[i].right<<endl;
return 0;
}
1797

被折叠的 条评论
为什么被折叠?



