图的操作

来源:互联网 发布:大数据行业研究报告 编辑:程序博客网 时间:2024/04/30 17:48

#include <iostream>
#include <queue>
#include <stack>
using namespace std;

typedef char vertextype; //顶点数据类型
typedef int adjtype; //权值类型
/////邻接矩阵存储结构//////
#define MAXVAL 99999 //设最大值
#define MAXNUM 20 //最大顶点个数
struct MGraph
{
 vertextype vex[MAXNUM];//用一维数组表示顶点
 adjtype arcs[MAXNUM][MAXNUM];//用二维数组表示邻接矩阵
 int n;//图的当前顶点数
 int e;//图的当前边数
};//邻接矩阵


///////邻接表存储结构/////
#define M 50
struct node
{
 int adjvex;//邻接点域
 node *link;//指针域4
 adjtype info;//权值信息
};
struct headnode
{
 vertextype vexdata;//顶点数据域
 node *firstarc;//指针指向链表中第一个节点
};
struct ALGraph
{
 headnode adjlist[M];
 int n;//顶点个数
};//邻接表


void dispgraph(ALGraph ALG);//打印图邻接表
void dispgraph_N(ALGraph ALN);//打印网邻接表

////无向图函数////
void CreatUDG_M(MGraph &MG);
void CreatUDG_ALG(ALGraph &ALG);
void DFS(ALGraph ALG);
void BFS(ALGraph ALG);

////无向网函数////
void CreatUDN_M(MGraph &MN);
void CreatUDN_ALG(ALGraph &ALN);
void Mini_PRIM(MGraph MN);
void Mini_KRASKAL(MGraph MN);

////有向图函数////
void CreatDG_M(MGraph &MN);
void CreatDG_ALG(ALGraph &ALN);
void Topo_Sort(ALGraph ALN);

////有向网函数////
void CreatDN_M(MGraph &MN);
void CreatDN_ALN(ALGraph &ALN);
void Criticla_Path(ALGraph ALN);
void Shortest_Path(MGraph MN);


void ShowMainMenu()
{
 cout<<"/n";
 cout<<"  ***************图的基本操作及应用******************/n";
 cout<<"  *  1 无向图的基本操作及应用                       */n";
 cout<<"  *  2 无向网的基本操作及应用                       */n";
    cout<<"  *  3 有向图的基本操作及应用                       */n";
 cout<<"  *  4 有向网的基本操作及应用                       */n";
 cout<<"  *  5 退出                                         */n";
 cout<<"  ***************************************************/n";
}

void UDG()//无向图
{
 MGraph MG;//邻接矩阵存储
 ALGraph ALG;//邻接表存储
 int n;
 do
 {
  cout<<"/n";
  cout<<"  ***************无向图的基本操作及应用**************/n";
     cout<<"  *  1 创建无向图的邻接矩阵                         */n";
  cout<<"  *  2 创建无向图的邻接表                           */n";
     cout<<"  *  3 无向图的深度优先遍历                         */n";
     cout<<"  *  4 无向图的广度优先遍历                         */n";
  cout<<"  *  5 退出                                         */n";
     cout<<"  ***************************************************/n";
  cout<<"请选择操作:";
  cin>>n;
  switch(n)
  {
   case 1:
    CreatUDG_M(MG);//创建无向图的邻接矩阵
    break;
   case 2:
    CreatUDG_ALG(ALG);//创建无向图的邻接表
    dispgraph(ALG);//打印邻接表
    break;
   case 3:
    DFS(ALG);//无向图的深度优先遍历
    break;
   case 4:
    BFS(ALG);//无向图的广度优先遍历
    break;
   default:
    if (n!=5)
     cout<<"错误,重新输入/n";
  }
 }while(n!=5);
}

void UDN()//无向网
{
 MGraph MN;
 ALGraph ALN;
 int n;
 do{
  cout<<"/n";
  cout<<"  ***************无向网的基本操作及应用**************/n";
     cout<<"  *  1 创建无向网的邻接矩阵                         */n";
  cout<<"  *  2 创建无向网的邻接表                           */n";
     cout<<"  *  3 prim算法求最小生成树                         */n";
  cout<<"  *  4 kraskal算法求最小生成树                      */n";
  cout<<"  *  5 退出                                         */n";
     cout<<"  ***************************************************/n";
  cout<<"请选择操作:";
  cin>>n;
  switch(n)
  {
   case 1:
    CreatUDN_M(MN);//创建无向网的邻接矩阵
    break;
   case 2:
    CreatUDN_ALG(ALN);//创建无向网的邻接表
    dispgraph_N(ALN);//打印无向网邻接表
    break;
   case 3:
    Mini_PRIM(MN);//prim算法求最小生成树
    break;
   case 4:
    Mini_KRASKAL(MN);//kraskal算法求最小生成树
    break;
   default:
    if (n!=5)
     cout<<"错误,重新输入/n";
  }
 }while(n!=5);
 
}

void DG()//有向图
{
 MGraph MG;//邻接矩阵存储
 ALGraph ALG;//邻接表存储
 int n;
 do
 {
  cout<<"/n";
  cout<<"  ***************有向图的基本操作及应用**************/n";
     cout<<"  *  1 创建有向图的邻接矩阵                         */n";
  cout<<"  *  2 创建有向图的邻接表                           */n";
     cout<<"  *  3 拓扑排序                                     */n";
  cout<<"  *  4 退出                                         */n";
     cout<<"  ***************************************************/n";
  cout<<"请选择操作:";
  cin>>n;
  switch(n)
  {
   case 1:
    CreatDG_M(MG);
    break;
   case 2:
    CreatDG_ALG(ALG);
    dispgraph(ALG);
    break;
   case 3:
    Topo_Sort(ALG);
    break;
   default:
    if (n!=4)
     cout<<"错误,重新输入/n";
  }
 }while(n!=4);
}


void DN()//有向网
{
 MGraph MN;
 ALGraph ALN;
 int n;
 do{
  cout<<"/n";
  cout<<"  ***************有向网的基本操作及应用**************/n";
     cout<<"  *  1 创建有向网的邻接矩阵                         */n";
  cout<<"  *  2 创建有向网的邻接表                           */n";
     cout<<"  *  3 关键路径                                     */n";
  cout<<"  *  4 单源顶点最短路径问题                         */n";
  cout<<"  *  5 退出                                         */n";
     cout<<"  ***************************************************/n";
  cout<<"请选择操作:";
  cin>>n;
  switch(n)
  {
   case 1:
    CreatDN_M(MN);//创建有向网的邻接矩阵
    break;
   case 2:
    CreatDN_ALN(ALN);//创建有向网的邻接表
    dispgraph_N(ALN);//打印有向网邻接表
    break;
   case 3:
    Criticla_Path(ALN);//关键路径
    break;
   case 4:
    Shortest_Path(MN);//最短路径
    break;
   default:
    if (n!=5)
     cout<<"错误,重新输入/n";
  }
 }while(n!=5);
 
}

void main()
{
 int n;
 do{
  ShowMainMenu();
  cout<<"请选择操作:";
  cin>>n;
  switch(n){
   case 1:
    UDG();//无向图
    break;
   case 2:
                UDN();//无向网
    break;
   case 3:
    DG();//有向图
    break;
   case 4:
    DN();//有向网
    break;
   default:
    if (n!=5)
     cout<<"错误,重新输入/n";
  }
 }while(n!=5);
}

//////////////////////////////////////////////////////////////////////
void dispgraph(ALGraph ALG)//打印图邻接表
{
 int i;
 node *p;
 for(i=1;i<=ALG.n;i++)
 {
  cout <<ALG.adjlist[i].vexdata;
  p = ALG.adjlist[i].firstarc;
  while(p != NULL)
  {
   cout <<" --";
   cout << ALG.adjlist[p->adjvex].vexdata;
   p=p->link;
  }
  cout << endl;
 }
}
void dispgraph_N(ALGraph ALN)//打印网邻接表
{
 int i;
 node *p;
 for(i=1;i<=ALN.n;i++)
 {
  cout <<ALN.adjlist[i].vexdata;
  p = ALN.adjlist[i].firstarc;
  while(p != NULL)
  {
   cout <<" --";
   cout << ALN.adjlist[p->adjvex].vexdata <<"("<<p->info<<")";
   p=p->link;
  }
  cout << endl;
 }
}


////无向图函数////
void CreatUDG_M(MGraph &MG)
{
 int i,j,k;
 cout <<"输入顶点数和边数:";
 cin >>MG.n>>MG.e;//输入图的顶点数和边数
 cout << "输入顶点:";
 for(i=1;i<=MG.n;i++)
  cin >> MG.vex[i];//构造顶点向量
 for(i=1;i<=MG.n;i++)
  for(j=1;j<=MG.n;j++)
   MG.arcs[i][j]=0;//初始化邻接矩阵
 for(k=1;k<=MG.e;k++)
 {
  cout<<"输入一条边依附的顶点的序号:";
  cin>>i>>j;//输入一条边依附的顶点的序号及权值
  MG.arcs[i][j]=1;
  MG.arcs[j][i]=1;//权值赋予邻接矩阵相应元素
 }
}
void CreatUDG_ALG(ALGraph &ALG)
{
 node *p;
 int i,j;
 char ch;
 cout << "输入顶点数:";
 cin >> ALG.n;
 cout <<"输入顶点信息:";
 for(i=1;i<=ALG.n;i++)
 {
  cin >> ch;//读入顶点信息
  ALG.adjlist[i].vexdata = ch;//设置顶点为字符型
  ALG.adjlist[i].firstarc =NULL;//将链表初始化为空
 }
 cout << "读入一条边依附的顶点序号:";
 cin >> i >> j;
 while((i>0)&&(j>0))//输入(i,j)为(0,0)作结束标记
 {
  p = new node;//生成邻接点序号为j的表结点
  p->adjvex = j;
  p->link = ALG.adjlist[i].firstarc;
  ALG.adjlist[i].firstarc = p;//结点j插入到第i个链表
  p = new node;//生成邻接点序号为i的表结点
  p->adjvex = i;
  p->link = ALG.adjlist[j].firstarc;
  ALG.adjlist[j].firstarc = p;//结点i插入到第j个链表
  cout << "读入一条边依附的顶点序号:";
  cin >> i >> j;
 }
}

void dfs(ALGraph ALG,int v,int flag[])
{
 node *p;
 int i;
 flag[v] = 1;
 cout << ALG.adjlist[v].vexdata << endl;//访问顶点i
 p = ALG.adjlist[v].firstarc;//p指向v的第一个邻接点
 while(p != NULL)
 {
  i = p->adjvex;//取出p指针所指的邻接点序号
  if(flag[i] == 0)
   dfs(ALG,i,flag);//对尚未访问的邻接点递归调用dfs算法
  p = p->link;//查找下一个邻接点
 }
}
void DFS(ALGraph ALG)
{
 int i;
 int flag[M];
 for(i = 1;i<=ALG.n;i++)
  flag[i] = 0;//初始化标志数组
 cout << "输入顶点序号:";
 cin>>i;
 dfs(ALG,i,flag);//以i为顶点深度优先遍历
}

void bfs(ALGraph ALG,int v,int flag[])
{
 queue <int> q;//q为辅助队列
 node *p;
 cout << ALG.adjlist[v].vexdata << endl;//访问顶点v
 flag[v] = 1;
 q.push(v);//刚访问过的顶点序列入队列
 while(!q.empty())//当队列不为空时
 {
  v=q.front();//访问过的顶点值传给v
  q.pop();//顶点出队列
  p = ALG.adjlist[v].firstarc;//p指向第一个邻接点
  while(p != NULL)
  {
   v = p ->adjvex;
   if(flag[v] == 0)//如果未访问
   {
    flag[v] = 1;//设为访问
    cout << ALG.adjlist[v].vexdata << endl;//访问顶点
    q.push(v);//被访问过的顶点入队列
   }
   p = p->link;//查找下一个邻接点
  }
 }
}
void BFS(ALGraph ALG)
{
 int i;
 int flag[M];//定义标志数组
 for(i=1;i<=ALG.n;i++)//初始化标志数组
  flag[i] = 0;
 cout << "输入顶点序号:";
 cin>>i;
 bfs(ALG,i,flag);//以i为顶点广度深度优先遍历
}
////无向网函数////
void CreatUDN_M(MGraph &MN)
{
 int i,j,k;
 int w;
 cout <<"输入顶点数和边数:";
 cin >>MN.n>>MN.e;//输入图的顶点数和边数
 cout << "输入顶点:";
 for(i=1;i<=MN.n;i++)
  cin >> MN.vex[i];//构造顶点向量
 for(i=1;i<=MN.n;i++)
  for(j=1;j<=MN.n;j++)
   MN.arcs[i][j]=MAXVAL;//初始化邻接矩阵
 for(k=1;k<=MN.e;k++)
 {
  cout<<"输入一条边依附的顶点的序号及权值:";
  cin>>i>>j>>w;//输入一条边依附的顶点的序号及权值
  MN.arcs[i][j]=w;
  MN.arcs[j][i]=w;//权值赋予邻接矩阵相应元素
 }
}
void CreatUDN_ALG(ALGraph &ALN)
{
 node *p;
 int i,j,k;
 char ch;
 cout << "输入顶点数:";
 cin >> ALN.n;
 cout <<"输入顶点信息:";
 for(i=1;i<=ALN.n;i++)
 {
  cin >> ch;//读入顶点信息
  ALN.adjlist[i].vexdata = ch;//设置顶点为字符型
  ALN.adjlist[i].firstarc =NULL;//将链表初始化为空
 }
 cout << "读入一条边依附的顶点序号及权值:";
 cin >> i >> j >> k;
 while((i>0)&&(j>0))//输入(i,j)为(0,0)作结束标记
 {
  p = new node;//生成邻接点序号为j的表结点
  p->info = k;
  p->adjvex = j;
  p->link = ALN.adjlist[i].firstarc;
  ALN.adjlist[i].firstarc = p;//结点j插入到第i个链表
  p = new node;//生成邻接点序号为i的表结点
  p->info = k;
  p->adjvex = i;
  p->link = ALN.adjlist[j].firstarc;
  ALN.adjlist[j].firstarc = p;//结点i插入到第j个链表
  cout << "读入一条边依附的顶点序号及权值:";
  cin >> i >> j >> k;
 }
}
void Mini_PRIM(MGraph MN)
{
 struct//辅助数组
 {
  int adjvex;//记录前驱顶点序号
  int lowcost;
 }closedge[M];
 int k;
 cout << "输入根的序号:";
 cin >> k;
 int i,j,p,v;
 int min;
 for(i = 1; i<=MN.n;i++)//辅助数组初始化
  if(i != k)
  {
   closedge[i].adjvex = k;
   closedge[i].lowcost = MN.arcs[k][i];
  }
 closedge[k].lowcost = 0;
 for(i = 1; i < MN.n; i++)//进行n-1次循环,每次求出最小生成树的第j条边
 {
  p = i;
  min = MAXVAL;
  for(v =1; v <= MN.n; v++)//选最小权值及对应的顶点
   if((closedge[v].lowcost != 0)&&(closedge[v].lowcost < min))
   {
    min = closedge[v].lowcost;
    p = v;
   }
  cout <<"<"<< MN.vex[closedge[p].adjvex] <<","<< MN.vex[p] <<"> "<< min <<endl;//输出最小边及权值
  closedge[p].lowcost = 0;//将顶点p加到生成树上
  for(j = 1; j <= MN.n; j++)
   if(MN.arcs[p][j] < closedge[j].lowcost)
   {
    closedge[j].lowcost = MN.arcs[p][j];//修改未选出点的最小权值
    closedge[j].adjvex = p;//记下在生成树一端的顶点序号,新顶点并入生成树
   }
 }
}
void Mini_KRASKAL(MGraph MN)
{
 int a[M];//顶点辅助值,用来判断是否连成回路
 int i,j,k,p=1,q=1;
 int count=1;
 int min;//记录最小边
 for(i = 1; i <= MN.n; i++)//初始化辅助值
  a[i] =i;
 
 while(count < MN.n)//选出n-1条边
 {
  min=MAXVAL;
  for(j = 1;j<=MN.n;j++)
  {  
   for(k=1;k<=MN.n;k++)
   { 
    if((MN.arcs[j][k] != 0) && (MN.arcs[j][k] < min))
    {
     if(a[j]!=a[k])//判断是否会构成回路
     {
      min = MN.arcs[j][k];
      p = j;
      q = k;
     } 
    }
   }
  }
  MN.arcs[p][q] = 0;//
  MN.arcs[q][p] = 0;//选中的边权值置为0
  int m=a[p];
  for(i=1;i<MN.n;i++)//将连接在一起的顶点辅助值改为相同
   if(a[i]==m)
    a[i]=a[q];
  count++;
  cout <<"<"<< MN.vex[p] <<","<< MN.vex[q] <<"> "<<min<<endl;//输出选中的边的顶点及权值
 }
}

////有向图函数////
void CreatDG_M(MGraph &MG)
{
 int i,j,k;
 cout <<"输入顶点数和边数:";
 cin >>MG.n>>MG.e;//输入图的顶点数和边数
 cout << "输入顶点:";
 for(i=1;i<=MG.n;i++)
  cin >> MG.vex[i];//构造顶点向量
 for(i=1;i<=MG.n;i++)
  for(j=1;j<=MG.n;j++)
   MG.arcs[i][j]=0;//初始化邻接矩阵
 for(k=1;k<=MG.e;k++)
 {
  cout<<"输入一条边依附的顶点的序号:";
  cin>>i>>j;//输入一条边依附的顶点的序号及权值
  MG.arcs[i][j]=1;//权值赋予邻接矩阵相应元素
 }
}
void CreatDG_ALG(ALGraph &ALG)
{
 node *p;
 int i,j;
 char ch;
 cout << "输入顶点数:";
 cin >> ALG.n;
 cout <<"输入顶点信息:";
 for(i=1;i<=ALG.n;i++)
 {
  cin >> ch;//读入顶点信息
  ALG.adjlist[i].vexdata = ch;//设置顶点为字符型
  ALG.adjlist[i].firstarc =NULL;//将链表初始化为空
 }
 cout << "读入一条边依附的顶点序号:";
 cin >> i >> j;
 while((i>0)&&(j>0))//输入(i,j)为(0,0)作结束标记
 {
  p = new node;//生成邻接点序号为j的表结点
  p->adjvex = j;
  p->link = ALG.adjlist[i].firstarc;
  ALG.adjlist[i].firstarc = p;//头插法将结点j插入到第i个链表
  cout << "读入一条边依附的顶点序号:";
  cin >> i >> j;
 }
}

void InDegree(ALGraph ALG,int degree[])//求个顶点的入度
{
 node *p;
 int i,k;
 for(i=1;i<=ALG.n;i++)
 {
  p = ALG.adjlist[i].firstarc;
  while(p != NULL)
  {
   k = p->adjvex;
   degree[k]++;
   p=p->link;
  }
 }
}
void Topo_Sort(ALGraph ALG)
{
 int i,m,k;
 int degree[M];
 for(i=1;i<=ALG.n;i++)
  degree[i] = 0;//入度初始化为0
 InDegree(ALG,degree);
 stack <int> S;
 for(i=1;i<=ALG.n;i++)
  if(degree[i] == 0)
   S.push(i);
 int count=0;//对输出顶点计数
 while(!S.empty())
 {
  m=S.top();
  S.pop();
  cout<< ALG.adjlist[m].vexdata << endl;//输出入度为0的顶点
  ++count;//计数
  for(node *p = ALG.adjlist[m].firstarc;p != NULL; p=p->link)
  {
   k = p->adjvex;
   if((--degree[k]) == 0)//若入度减为0,则入栈
    S.push(k);
  }
 }
 if(count < ALG.n)
  cout << "该有向图有回路!";
}

////有向网函数///////
void CreatDN_M(MGraph &MN)
{
 int i,j,k;
 float w;
 cout <<"输入顶点数和边数:";
 cin >>MN.n>>MN.e;//输入图的顶点数和边数
 cout << "输入顶点:";
 for(i=1;i<=MN.n;i++)
  cin>>MN.vex[i];//构造顶点向量
 for(i=1;i<=MN.n;i++)
  for(j=1;j<=MN.n;j++)
   MN.arcs[i][j]=MAXVAL;//初始化邻接矩阵
 for(k=1;k<=MN.e;k++)
 {
  cout<<"输入一条边依附的顶点的序号及权值:";
  cin>>i>>j>>w;//输入一条边依附的顶点的序号及权值
  MN.arcs[i][j]=w;//权值赋予邻接矩阵相应元素
 }
}
void CreatDN_ALN(ALGraph &ALN)
{
 node *p;
 int i,j,k;
 char ch;
 cout << "输入顶点数:";
 cin >> ALN.n;
 cout <<"输入顶点信息:";
 for(i=1;i<=ALN.n;i++)
 {
  cin >> ch;//读入顶点信息
  ALN.adjlist[i].vexdata = ch;//设置顶点为字符型
  ALN.adjlist[i].firstarc =NULL;//将链表初始化为空
 }
 cout << "读入一条边依附的顶点序号及权值:";
 cin >> i >> j >> k;
 while((i>0)&&(j>0))//输入(i,j)为(0,0)作结束标记
 {
  p = new node;//生成邻接点序号为j的表结点
  p->info = k;
  p->adjvex = j;
  p->link = ALN.adjlist[i].firstarc;
  ALN.adjlist[i].firstarc = p;//结点j插入到第i个链表
  cout << "读入一条边依附的顶点序号及权值:";
  cin >> i >> j >> k;
 }
}

bool TopoOrder(ALGraph ALN,stack <int>&T,int ve[])//求ve并将逆序存入T
{
 int i,m,k;
 stack <int> S;
 int degree[M];
 for(i=1;i<=ALN.n;i++)
 { 
  degree[i] = 0;//入度初始化为0
  ve[i]=0;
 }
 InDegree(ALN,degree);
 for(i=1;i<=ALN.n;i++)
  if(degree[i] == 0)
   S.push(i);
 int count=0;//对输出顶点计数
 while(!S.empty())
 {
  m=S.top();
  T.push(m);//将入度为0的顶点入栈
  S.pop();
  ++count;//计数
  for(node *p = ALN.adjlist[m].firstarc;p != NULL; p=p->link)
  {
   k = p->adjvex;//对k号顶点的每个邻接点入度减1
   if((--degree[k]) == 0)//若入度减为0,则入栈
    S.push(k);
     if((ve[m]+ p->info) > ve[k])
    ve[k]=ve[m]+p->info;
  }
 }
 if(count < ALN.n)
  return false;
 else
  return true;

}
void Criticla_Path(ALGraph ALN)
{
 int ve[M],vl[M];
 int j,k,ee,el;
 node *p;
 stack <int> S;
 if(!TopoOrder(ALN,S,ve))
  cout << "存在回路";
 else
 {
  for(int i =1;i<=ALN.n;i++)
   vl[i]=ve[ALN.n];
  while(!S.empty())//逆序求vl
  {
   for(j=S.top(),S.pop(),p=ALN.adjlist[j].firstarc;p!=NULL;p=p->link)
   {
    k=p->adjvex;
    if(vl[k]-p->info < vl[j])
     vl[j] =vl[k]-p->info;
   }
  }
  cout << "关键路径为:";
  for(j = 1;j<=ALN.n;++j)
   for(p=ALN.adjlist[j].firstarc;p!=NULL;p=p->link)
   {
    k=p->adjvex;
    ee=ve[j];//起始点最早发生时间
    el=vl[k]-p->info;//活动最晚发生时间减去活动权值
    if(ee==el)//ee与el相等则为关键路径
     cout <<"<"<<j << ',' << k<<">"<< ' ';
   }
 }
}

void Shortest_Path(MGraph MN)
{
 int i;//源点
 cout << "输入源点:";
 cin >> i;
 int pre[M];
 float dist[M];
 int j,k,p,v;
 int min;
 for(j=1;j<=MN.n;j++)
 {
  dist[j]=MN.arcs[i][j];
  if(dist[j]<MAXVAL)
   pre[j]=i;
  else
   pre[j]=0;
  MN.arcs[j][j]=0;
 }
 dist[i]=0;pre[i]=0;
 MN.arcs[i][i]=1;//源点设置为被选出
 for(k=1;k<=MN.n;k++)
 {
  min=MAXVAL;
  j=-1;
  for(p=1;p<=MN.n;p++)//选出最短路径的点
   if((MN.arcs[p][p]==0)&&dist[p]<min)
   {
    j=p;
    min=dist[p];
   }
  if(j==-1)
   break;
  else
  {
   MN.arcs[j][j]=1;
   for(v=1;v<=MN.n;v++)//更新路径为下次作选择准备
    if((MN.arcs[v][v]==0)&&((min+MN.arcs[j][v]) < dist[v]))
    {
     dist[v]=min+MN.arcs[j][v];
     pre[v]=j;
    }
  }
 }
 cout << "选择终点:";
 cin >> i;
 cout << "最短路径为";
 while(pre[i] != 0)
 {
  i=pre[i];
  cout << i <<' ';
 }
 
}
///////////////////////////////////////////////////////////////////////