最小生成树(2)

来源:互联网 发布:金融大数据平台 编辑:程序博客网 时间:2024/06/05 11:07

在这个程序中有一个很重要的思想是等价类的思想:首先我们是将一个无向图中所有的顶点都看成一个连通分量,然后这些个顶点都是一个等价类,这个时候我们用弧去连接这些等价类,两个顶点连接之后又称为一个等价类,然后等价类之间,我们不断的添加弧,知道最后所有的等价类称为一个等价类。等价类的思想分析请看:最小生成树(3)

#include<iostream>

using namespace std;
#define MAX_VERTEX_NUM 20
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int InfoType;
typedef int Status;
typedef int VertexType;
//定义一个边的节点
typedef struct ArcNode
{
int  adjvex;//该弧所指向顶点的位置
struct ArcNode *nextarc;//指向下一条弧的指针
InfoType info;//该弧相关的信息指针
}ArcNode;
//定义头节点信息
typedef struct VNode
{
   VertexType data;
   ArcNode *firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertice;//用来记录顶点的名称
int vexnum,arcnum;//图中的当前的节点和弧度数目
int kind;//图的类型
}ALGraph;
typedef struct Side
{
int data1,data2;
int value;


}Side;
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define STACK_INIT_SIZE 100//存储空间的初始分配量
#define STACKINCREMENT 10//存储空间的分配的增量
#define maxNum 100 //定义邻接举证的最大定点数  
int visited[maxNum];//通过visited数组来标记这个顶点是否被访问过,0表示未被访问,1表示被访问  
int DFS_Count;//连通部件个数,用于测试无向图是否连通,DFS_Count=1表示只有一个连通部件,所以整个无向图是连通的  
int pre[maxNum];  
int post[maxNum];  
int point;//pre和post的值
typedef struct
{
Side *base;
Side *top;
int stacksize;//当前分配的存储空间,
}SqStack;
typedef struct
{
Side *elem;//存储空间的基址
int length;
int listsize;//当前发分配的side单位的个数
}SqList;
//判断是否有环要用到
typedef struct  
{  
    char v[50];//图的顶点信息  
    int e[50][50];//图的顶点信息  
    int vNum;//顶点个数  
    int eNum;//边的个数  
}graph;


typedef struct QNode
{
int data;
}QNode;
#define MAX_TREE_SIZE 100
typedef struct PTNode
{
QNode data;
int parent;//双亲的位置
}PTNode;
typedef struct 
{
PTNode node[MAX_TREE_SIZE];
int r,n;//根的位置和节点的数目
}PTree;
typedef PTree MFSet;  
Side array[30];
int array1[30];
//初始化线性表
Status InitList_Sq(SqList *L)
{
L->elem=(Side *)malloc(LIST_INIT_SIZE *sizeof(Side));
if(!L->elem) return ERROR;
L->length=0;
L->listsize=LIST_INIT_SIZE;
return OK;
}
//向顺序表中插入元素
void sideEqual(Side *s1,Side *s2)
{
s1->data1=s2->data1;
s1->data2=s2->data2;
s1->value=s2->value;
}
Status ListInsert_Sq(SqList *L,int i,Side *e)
{
if(i<1 || i>L->length+1) 
{
return ERROR;
cout<<"i的值不合法"<<endl;


}
if(L->length>=L->listsize)
{
L->elem=(Side *)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(Side));
if(!L->elem)
exit(OVERFLOW);
L->listsize+=LISTINCREMENT;
}
Side *q=&L->elem[i-1];
Side *p;
for(p=&(L->elem[L->length-1]);p>=q;--p)
sideEqual(p+1,p);
sideEqual(q,e);
++L->length;
return OK;
}
Status CreateUDN(ALGraph *G,SqList *L)
{
int a,b,value;
int i=0,j=0;
cout<<"请输入图的顶点数目,边的数目,图的类型(0为无向图): "<<endl;
     cin>>G->vexnum>>G->arcnum>>G->kind;
cout<<"请输入顶点:"<<endl;
//顶点是链表的头结点,然后这个链表的其他的结点都是一些边
for(i;i<G->vexnum;i++)
{
cin>>G->vertice[i].data;//读入顶点的信息
G->vertice[i].firstarc=NULL;//此时顶点作为是链表的头结点,谁也不指向
}
//接着要做的事情也即是填充边
cout<<"请输入边的信息:(a,b,value)"<<endl;
for(i=0;i<G->arcnum;i++)
{
cin>>a>>b>>value;
L->elem[i].data1=a;
L->elem[i].data2=b;
L->elem[i].value=value;
L->length++;
ArcNode *S=(ArcNode *)malloc(sizeof(ArcNode));
S->adjvex=b;
S->info=value;
S->nextarc=G->vertice[a].firstarc;
G->vertice[a].firstarc=S;
ArcNode *S1=(ArcNode *)malloc(sizeof(ArcNode));
S1->adjvex=a;
S1->info=value;
S1->nextarc=G->vertice[b].firstarc;
G->vertice[b].firstarc=S1;
}
return OK;
}
void showUDN(ALGraph *G)
{
ArcNode *V=(ArcNode *)malloc(sizeof(ArcNode));
for(int i=0;i<G->vexnum;i++)
{
cout<<G->vertice[i].data<<"----";
V=G->vertice[i].firstarc;
   while(V)
{
  cout<<V->adjvex<<"-----"<<V->info<<"------";
  V=V->nextarc;
}
cout<<endl;


}


}
void storyValue(ALGraph *G,SqList *L)
{    
int j=1; 
     for(int i=0;i<G->vexnum;i++)
{
ArcNode *V=(ArcNode *)malloc(sizeof(ArcNode));
V=G->vertice[i].firstarc;
while(V)
{
  Side *side=(Side *)malloc(sizeof(Side));
  side->data1=G->vertice[i].data;
  side->data2=V->adjvex;
  side->value=V->info;
  //将side存起来
  if(ListInsert_Sq(L,j,side))
        j++;
           V=V->nextarc;
}
}

}
void storyVlaue1(ALGraph *G,SqList *L)
{
ArcNode *V=(ArcNode *)malloc(sizeof(ArcNode));
     V=G->vertice[0].firstarc;
     L->elem[1].data1=G->vertice[0].data;
L->elem[1].data2=V->adjvex;
L->elem[1].value=V->info;


}
void showSqList(SqList *L)
{
int i=0;
for(i;i<L->length;i++)
{
cout<<"( "<<L->elem[i].data1<<" , "<<L->elem[i].data2<<" , "<<L->elem[i].value<<" )"<<endl;
}
}
Status LT(int k1,int k2)
{
if(k1>k2)
return OK;
else
return ERROR;
}
Status RT(int k1,int k2)
{
if(k1<k2)
return OK;
else
return ERROR;
}
//直接插入排序
//*******************************************************修改*********************
void InsertSort(SqList *L)
{
    int j;
for(int i=2;i<=L->length;++i)
{
if(LT(L->elem[i].value,L->elem[i-1].value))
sideEqual(&L->elem[0],&L->elem[i]);
sideEqual(&L->elem[0],&L->elem[i-1]);
for(j=i-2;LT(L->elem[0].value,L->elem[j].value);--j)
sideEqual(&L->elem[j+1],&L->elem[j]);
sideEqual(&L->elem[j+1],&L->elem[0]);
}
}
//***************************************************************************
void changeSqList(SqList *S,SqList *L)
{
     for(int i=1;i<=L->length;i++)
{
Side *side=(Side *)malloc(sizeof(Side));
    side->data1=L->elem[L->length-i].data1;
side->data2=L->elem[L->length-i].data2;
side->value=L->elem[L->length-i].value;
ListInsert_Sq(S,i,side);
}
}
//现在我需要做的是删除某一个线段
Status ListDelete_Sq(SqList *L,int i,Side *e)
{
if(i<1 || i>L->length)
return ERROR;
Side *p=&L->elem[i-1];
sideEqual(e,p);
Side *q=L->elem+L->length-1;
for(++p;p<=q;++p)
sideEqual(p-1,p);
      --L->length;
 return OK;
}
//初始化一个栈
Status InitStack(SqStack *stack)
{
stack->base=(Side *)malloc(STACK_INIT_SIZE *sizeof(Side));
if(!stack->base)
exit(OVERFLOW);
    stack->top=stack->base;
stack->stacksize=STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack *stack,Side *e)
{
//插入元素e为新的栈顶元素
if(stack->top-stack->base>=stack->stacksize)
{
stack->base=(Side *)realloc(stack->base,(stack->stacksize+STACKINCREMENT)*sizeof(Side));
if(!stack->base) exit(OVERFLOW);
stack->top=stack->base+stack->stacksize;
stack->stacksize+=STACKINCREMENT;
}
sideEqual(stack->top,e);
stack->top++;
return OK;
}
int getStackLen(SqStack *stack)
{
return stack->top-stack->base;
}
//显示栈内的元素
void showStack(SqStack *S)
{
Side *side=(Side *)malloc(sizeof(Side *));
int i=0;
side=S->base;
int length=S->top-S->base;
while(i<length)
{
 cout<<"( "<<side->data1<<" , ";
 cout<<side->data2<<" , "<<side->value<<" )"<<endl;
 i++;
 side++;
}
 
}


void Initial(MFSet *S,ALGraph *G)
{


for(int i=0;i<=G->vexnum;i++)
{
S->node[i].data.data=G->vertice[i].data;
S->node[i].parent=-1;
}
S->n=G->vexnum;
}
//找到元素i所属于的集合
int find_mfset(MFSet *S,int i)
{
if(i<0 || i>S->n)
return -1;
for(int j=i;S->node[j].parent>0;j=S->node[j].parent);
return j;
}
//两个不相干的集合合并
int  mix_mfset(MFSet *S,int i,int j)
{
if(i<0 || i>S->n || j<0 || j>S->n)
return ERROR;
    S->node[i].parent=j;
return OK;
}


int main()
{
    ALGraph Graph;
SqList L,S;
SqStack stack; 
InitList_Sq(&L);
InitList_Sq(&S);
CreateUDN(&Graph,&L);
showUDN(&Graph);
    Side *side=(Side *)malloc(sizeof(Side));
side->data1=0;
side->data2=0;
side->value=0;
ListInsert_Sq(&L,1,side);
    InsertSort(&L);
changeSqList(&S,&L);
showSqList(&S);
    InitStack(&stack);
MFSet SF;
    Initial(&SF,&Graph);
     int a,b,temp,i;
a=S.elem[0].data1;
     b=S.elem[0].data2;
if(a>b)
{   temp=a;
a=b;
b=temp;
}
     mix_mfset(&SF,a,b);
     a=S.elem[1].data1;
     b=S.elem[1].data2;
if(a>b)
{
temp=a;
a=b;
b=temp;
}
    mix_mfset(&SF,a,b);
Push(&stack,&S.elem[0]);
Push(&stack,&S.elem[1]);
i=2;
    while(i<S.length && stack.top-stack.base<Graph.vexnum-1)
{    
a=S.elem[i].data1;
        b=S.elem[i].data2;
   if(a>b)
{
temp=a;
a=b;
b=temp;
}
if(find_mfset(&SF,a)!=find_mfset(&SF,b) && find_mfset(&SF,a)!=b)
{

            mix_mfset(&SF,a,b);
Push(&stack,&S.elem[i]);


}
i++;
}
cout<<"得到最小生成树:"<<endl;
showStack(&stack);
//显示数组中的元素
    return 0;
}
0 0
原创粉丝点击