prime and kluskal

//本算法未采用生成树,只用输出表示找到了,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;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值