数据结构上机实验(6个)

关于文件的输入输出,只要在主函数中添加:

freopen("E:\read9.txt","r",stdin);
freopen("E:\write9.txt","w",stdout);

即可。

其余地方的输入输出不变,但是必须用scanf和printf进行输入输出。

实验一  迷宫问题(bfs)

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"queue"
#include"string.h"
#include"cmath"
#include"stack"
#include"fstream"
#define mx 105
#define inf 1000
using namespace std;
int n,m;
int sx,sy,ex,ey;
int  maze[mx][mx],vis[mx][mx];
int dir[8][2]= {{0,1},{0,-1},{1,0},{-1,0},{-1,-1},{-1,1},{1,-1},{1,1}};
bool judge(int x,int y)
{
    if(maze[x][y]==0&&x>=0&&x<n&&y>=0&&y<m)
    {
        return true;
    }
    return false;
}
void output(int step)
{        
    int i;
    stack<int>path;
    path.push(ex*m+ey);
    printf("%s%d
","最少步骤是:",step);
    int x=ex,y=ey,dx,dy;
    while(vis[x][y]!=0)
    {
        for(i=0;i<8;i++)
        {
            dx=x+dir[i][0];
            dy=y+dir[i][1];
            if(dx>=0&&dx<n&&dy>=0&&dy<m)
            if(vis[dx][dy]==vis[x][y]-1)
            {
                path.push(dx*m+dy);
                break;
            }
        }
        x=dx;y=dy;
    }
    printf("%s","最短路径为:");
    while(!path.empty())
     {
         int u=path.top();
         path.pop();
         x=u/m;y=u%m;
         if(x!=ex||y!=ey)
        printf("%s%d%s%d%s%s","(",x,",",y,")","->");
         else printf("%s%d%s%d%s

","(",x,",",y,")");
     }

}
void bfs(int step)
{
    queue<int>q;
    int i,x,y,dx,dy,u;
    x=sx;y=sy;
    u=x*m+y;
    q.push(u);
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        x=u/m;y=u%m;
        if(x==ex&&y==ey)
        {
            output(step);
            return;
        }
        int flag=1;
        step=vis[x][y];
        for(i=0;i<8;i++)
        {
            dx=x+dir[i][0];
            dy=y+dir[i][1];
            if(judge(dx,dy))
            {
                   if(flag){step++;flag=0;}
                    maze[dx][dy]=1;
                    if(step<vis[dx][dy])
                    vis[dx][dy]=step;
                    u=dx*m+dy;
                    q.push(u);

            }
        }
    }
    printf("%s","没有满足条件的通路!
");
}
int main()
{
    int i,j;
    freopen("C://read.txt","r",stdin);
    freopen("C://write.txt","w",stdout);
    while(scanf("%d%d",&n,&m),n||m)
    {
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
                {scanf("%d",&maze[i][j]);vis[i][j]=inf;}
        }
        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
        maze[sx][sy]=1;
        vis[sx][sy]=0;
        bfs(0);
    }
    return 0;
}
View Code

实验二  锦标赛问题(简单的分治思想)

#include"iostream"
#include"stdio.h"
#include"cmath"
#include"string.h"
#include"algorithm"
#include"queue"
using namespace std;
const int mx=1005;
int calendar[mx][mx];//日程表
FILE*  rfile=fopen("E:\read2.txt","r");
FILE*  wfile=fopen("E:\write2.txt","w");//文件读写
void championship(int k)
{
    int i,j,t;
    calendar[1][1]=1;//只有两个人比赛的情况
    calendar[1][2]=2;
    calendar[2][1]=2;
    calendar[2][2]=1;
    int temp=1;
    for(t=1;t<k;t++)
    {
        temp*=2;
        for(i=1;i<=temp;i++)
        {
            for(j=1;j<=temp;j++)
            {
                calendar[i+temp][j+temp]=calendar[i][j];
            }
        }
      for(i=1;i<=temp;i++)//用分治的方式打表
            {
                for(j=1;j<=temp;j++)
                {
                    calendar[i+temp][j]=calendar[i][j]+temp;
                }
            }

       for(i=temp+1;i<=temp*2;i++)
            {
                for(j=1;j<=temp;j++)
                {
                    calendar[i-temp][j+temp]=calendar[i][j];
                }
            }
    }

    int n=pow(2,k);
    for(i=1;i<=n;i++)//日程表的输出
    {
        for(j=1;j<=n;j++)
            fprintf(wfile,"%d ",calendar[i][j]);
        fprintf(wfile,"%s
","");
    }
    fprintf(wfile,"%s
","");//文件输出
}
int main()
{
    int k,icase=0;
    while((fscanf(rfile,"%d",&k),k!=-1))
    {
        fprintf(wfile,"%s%d%s
","Case ",++icase," :");
        fprintf(wfile,"%s%d
","input k :",k);
        championship(k);
    }
    fclose(wfile);
    fclose(rfile);
    return 0;
}
View Code

实验三 kruskal算法(最小生成树)

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"cmath"
#include"string.h"
#include"string"
using namespace std;

const int mx=105;
const int inf=32767;
FILE*  rfile=fopen("E:\read3.txt","r");
FILE*  wfile=fopen("E:\write3.txt","w");//文件读写
struct Edge//记录边的两个端点和权值
{
    int u;
    int v;
    int w;
};

struct Mgraph
{
    int edges[mx][mx];//存储边
    int n;//顶点数
};

struct UFStree//并查集的数据结构
{
    int data;//节点对应的编号
    int  parent;//节点对应双亲下标
    int rank;//节点对应秩
};

bool cmp(const Edge a,const Edge b)
{
    return a.w<b.w;
}
void Make_set(UFStree t[],int n)//初始化
{
    for(int i=0;i<n;i++)
    {
        t[i].rank=0;
        t[i].parent=i;
    }
}

int Find_set(UFStree t[],int  x)//查找集合的代表元素
{
    while(x!=t[x].parent)
        x=t[x].parent;
    return x;
}

void Union(UFStree t[],int x,int y)//将两个集合并为一个
{
    x=Find_set(t,x);
    y=Find_set(t,y);
    if(t[x].rank>t[y].rank)//将秩小的作为秩大的子集
        t[y].parent=x;
    else
    {
        t[x].parent=y;
        if(t[x].rank==t[y].rank) t[y].rank++;
    }
}

void  Kruskal(Mgraph g)//求最小生成树的算法
{

    int i,j,k,u1,v1,sn1,sn2;
    UFStree t[mx];
    Edge E[mx];
    k=1;                //E数组的下标从1开始
    for(i=0;i<g.n;i++)   //由g产生的边集E
        for(j=0;j<g.n;j++)
    {
        if(g.edges[i][j]!=0&&g.edges[i][j]!=inf)//取出图的邻接矩阵中所有的边
        {
            E[k].u=i;E[k].v=j;E[k++].w=g.edges[i][j];
        }
    }
    sort(E,E+k,cmp);//按边的权值从小到大排序
    Make_set(t,g.n);
    k=1;//k表示当前构造生成树的第几条边,初值为1
    j=1;//E中边的下标,初值为1
    while(k<g.n)
    {
        u1=E[j].u;
        v1=E[j].v;
        sn1=Find_set(t,u1);
        sn2=Find_set(t,v1);
        if(sn1!=sn2)//两定顶点属于不同的集合,该边是最小生成树的一条边
        {
            fprintf(wfile,"%s%d%s%d%s%d
","(",u1,",",v1,"):",E[j].w);
            k++;//生成边数增1
            Union(t,u1,v1);//将 u1和v1两个顶点合并
        }
        j++;
    }
}

int main()
{
    Mgraph g;
    int i,j,n;
    fprintf(wfile,"%s

","输入顶点数为0时结束!");
    while(fscanf(rfile,"%d",&n),n)
    {
        fprintf(wfile,"%s%d
","输入图的顶点数目:",n);
        g.n=n;
        fprintf(wfile,"%s
","输入每个顶点与n个顶点边的权值:");
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
              {fscanf(rfile,"%d",&g.edges[i][j]);//取地址符很关键
               fprintf(wfile,"%d ",g.edges[i][j]);
              }
              fprintf(wfile,"%s
","");
        }
        fprintf(wfile,"%s
","输出构成最小生成树的边和顶点集:");
        Kruskal(g);
        fprintf(wfile,"%s
","");
    }
    fclose(wfile);//关闭文件
    fclose(rfile);
    return 0;
}
View Code

实验四  哈夫曼编码

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string"
#include"string.h"
#include"cmath"
#include"fstream"
using namespace std;
const int mx=105;
const int inf=32767;//表示无穷
FILE* rfile=fopen("E:\read4.txt","r");
FILE* wfile=fopen("E:\write4.txt","w");
struct htnode
{
    char data;//节点值
    double weight;//权重
    int parent;//双亲节点
    int lchild;//左孩子节点
    int rchild;//右孩子节点
};

struct hcode
{
    char cd[mx];//存放当前结点的哈夫曼码
    int start;//cd[start]~cd[n]存放哈夫曼码
};
void CreatHuffman(htnode ht[],int n)
{
    int i,j,k,lnode,rnode;
    double min1,min2;
    for(i=0;i<2*n-1;i++)//所有节点的相关域置初值-1
    {
        ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
    }
    for(i=n;i<2*n-1;i++)//构造哈弗曼树
    {
        min1=min2=inf;
        lnode=rnode=-1;//lnode和rnode为最小权重的两个结点位置
        for(k=0;k<=i-1;k++)//在ht[]中找权值最小的两个结点
        {
            if(ht[k].parent==-1)//只在尚未构造二叉树的结点中查找
            {
                if(ht[k].weight<min1)
            {
                min2=min1;rnode=lnode;
                min1=ht[k].weight;lnode=k;
            }
            else if(ht[k].weight<min2)
            {
                min2=ht[k].weight;rnode=k;
            }
            }
        }
        ht[i].weight=ht[lnode].weight+ht[rnode].weight;
        ht[i].lchild=lnode;ht[i].rchild=rnode;//ht[i]作为双亲结点
        ht[lnode].parent=i;ht[rnode].parent=i;
    }
}

void CreatHuffmanCode(htnode ht[],hcode hcd[],int n)
{
    int i,f,c;
    hcode hc;
    for(i=0;i<n;i++)//根据哈夫曼树求哈夫曼编码
    {
        hc.start=n;c=i;
        f=ht[i].parent;
        while(f!=-1)
        {
            if(ht[f].lchild==c)
                hc.cd[hc.start--]='0';
            else
                hc.cd[hc.start--]='1';
            c=f;f=ht[f].parent;
        }
        hc.start++;hcd[i]=hc;
    }
}
void display(htnode ht[],hcode hcd[],int n)
{
    for(int i=0;i<n;i++)
    {
        fprintf(wfile,"%c%s",ht[i].data,": ");
        for(int j=hcd[i].start;j<=n;j++)
            fprintf(wfile,"%c",hcd[i].cd[j]);
        fprintf(wfile,"%s
","");
    }
     fprintf(wfile,"%s
","");
}
int main()
{
    htnode ht[mx];
    hcode hcd[mx];
    char enter;//用于清除换行
    int n,i,j;
    while(fscanf(rfile,"%d",&n),n)
    {
        for(i=0;i<n;i++)
        {
            fscanf(rfile,"%c%c%lf",&enter,&ht[i].data,&ht[i].weight);
        }
        CreatHuffman(ht,n);
        CreatHuffmanCode(ht,hcd,n);
        display(ht,hcd,n);
    }
    fclose(wfile);
    fclose(rfile);
    return 0;
}
View Code

实验五  树和二叉树

 任务(1)和(2):

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string"
#include"string.h"
#include"Stack"
#include"queue"
#include"vector"
//顺序表ADT的定义
//datatype的定义
#ifndef datatype
#define datatype NODE
#define _ERROR NULL
#endif
FILE* rfile=fopen("E:\read5.txt","r");
FILE* wfile=fopen("E:\write5.txt","w");
//树结点的定义
struct Tnode{
    struct Tnode * lchild;
    struct Tnode * rchild;
    char* data;//data用于保存节点信息,类型为字符串
};
typedef struct Tnode * Bitree;
typedef struct Tnode * NODE;
struct Table{  //为了定义栈
    datatype* Table_head;
    int Length;
    int Max_Length;
};
typedef struct Table* mystable;

//栈ADT的定义
typedef struct Table* mystack;
//为顺序表分配空间,将所有数据初始化为init
mystable Assign(const int maxlen,datatype init)
{
    mystable temp;
    if((temp=(mystable)malloc(sizeof(struct Table)))!=NULL){//分配空间成功
        temp->Max_Length = maxlen;
        temp->Length=0;
        if((temp->Table_head=(datatype *)malloc(sizeof(datatype)*maxlen))!=NULL)
            for(int i=0;i<maxlen;i++)
                *(temp->Table_head+i)=init;
        else
            return NULL;
        return temp;
    }
    return NULL;
}

//判断表是否为空
int isEmpty(const mystable table)
{
    if (table==NULL)
        return -1;
    if(table->Length == 0)
        return 1;
    return 0;
}

//判断表是否为满
int isFull(const mystable table)
{
    if (table==NULL)
        return -1;
    if(table->Length == table->Max_Length)
        return 1;
    return 0;
}

//获取position位置的数据
datatype get(const mystable table,int position)
{
    if (position>table->Length-1 || position<0)
        return _ERROR;
    return *(table->Table_head + position);
}

//获取表长
int getLength(const mystable table)
{
    if (table==NULL)
        return -1;
    return table->Length;
}

//从表中删除一个数据
int Remove(const mystable table,int position)
{
    int i=0;
    if(table==NULL)
        return -1;
    if(position>table->Length-1 || position<0)
        return 0;
    for(i=position;i<table->Length-1;i++)
        *(table->Table_head+i)=*(table->Table_head+(i+1));
    table->Length--;
    return 1;
}

//插入一个数据到position位置
int Insert(mystable table,int position,datatype data)
{
    int i=0;
    if(table==NULL)
        return -1;
    if(position>table->Length || position<0)
        return 0;
    if(isFull(table)==0){
        for(i=table->Length;i>position;i--)
            *(table->Table_head+i)=*(table->Table_head+(i-1));
        *(table->Table_head+i)=data;
        table->Length++;
    }else{
        mystable temp;
        if((temp=(mystable)malloc(sizeof(struct Table)))==NULL)
            return -1;
       if((temp->Table_head=(datatype*) malloc(sizeof(datatype)*(table->Max_Length+1)))==NULL)
            return -1;
        temp->Length=table->Max_Length+1;
        temp->Max_Length=table->Max_Length+1;
        for(i=0;i<position;i++)
            *(temp->Table_head+i)=*(table->Table_head+i);
        *(temp->Table_head+i)=data;
        for(i++;i<temp->Length;i++)
            *(temp->Table_head+i)=*(table->Table_head+(i-1));
        free(table->Table_head);
        free(table);
        table=temp;
    }
    return 1;
}

//释放表占用的空间
int del(const mystable table)
{
    free(table->Table_head);
    free(table);
    return 1;
}
//在表的最后插入一个数据
int add(const mystable table,datatype x)
{
    return Insert(table,table->Length,x);
}
//初始化栈,分配空间
mystack initial()
{
    return Assign(100,0);
}

//从栈中弹出一个数据
datatype pop(mystack Stack)
{
    if(Stack==NULL)
        return _ERROR;
    if(isEmpty(Stack))
        return _ERROR;
    datatype data;
    data=get(Stack,Stack->Length-1);
    Remove(Stack,Stack->Length-1);
    return data;
}

//返回栈顶的数据但不弹出
datatype peek(mystack Stack)
{
    if(Stack==NULL)
        return _ERROR;
    if(isEmpty(Stack))
        return _ERROR;
    datatype data;
    data=get(Stack,Stack->Length-1);
    return data;
}

//向栈中压入数据
int push(mystack Stack,datatype x)
{
    return Insert(Stack,Stack->Length,x);
}


//分配一个新的树节点
NODE newNode(char* data)
{
    NODE temp=(NODE)malloc(sizeof(struct Tnode));
    if(temp==NULL)
        return NULL;
    temp->lchild=NULL;
    temp->rchild=NULL;
    temp->data=data;
    return temp;
}

//字符串转化为中缀顺序表,这是本实验的核心代码
mystable char_to_infix(char ex[])
{
    int length=strlen(ex);
    mystable infix=Assign(length,NULL);
    char* temp;
    for (int i = 0; i < length; i++) {
        if ((ex[i] >= '0' && ex[i] <= '9') || ex[i] == '.' ) {
        //若是数字字符则查询直到遇到一个不是数字的字符
            int Count=0;
            for(int j=i;(ex[j] >= '0' && ex[j] <= '9') || ex[j] == '.';j++,Count++);
            temp=(char *)malloc(sizeof(char)*(Count+1));
            for(int j=0;j<Count;j++)
                temp[j]=ex[i+j];
            temp[Count]='';
            add(infix,newNode(temp));
            i=i+Count-1;
        }else{
            temp=(char *)malloc(sizeof(char)*2);
            temp[0]=ex[i];temp[1]='';
            add(infix,newNode(temp));
        }
    }
    return infix;
}

//中缀表达式转化为后缀表达式
mystable infix_to_postfix(mystable infix)
{
    mystack Stack=initial();
    mystable postfix=Assign(getLength(infix),NULL);
    for (int i = 0; i < getLength(infix); i++) {
        char opF,opS;
        opF=get(infix,i)->data[0];
        if ((opF>='0' && opF<='9') || opF=='.' || (opF>='a' && opF<='z'))
        //数字则直接压入后缀表达式
            add(postfix,get(infix,i));
        else{
            if (getLength(Stack) == 0) {
                push(Stack,get(infix,i));
            } else if (opF == '(') {
                push(Stack,get(infix,i));
            } else if (opF == ')') {
            //遇到右括号,将栈中的数据依次弹出,直到遇到左括号
                do {
                    opS = peek(Stack)->data[0];
                    if (opS != '(')
                        add(postfix,pop(Stack));
                    else
                        pop(Stack);
                } while (opS != '(');
            } else {
            //比较优先级,若优先级高于栈顶元素则压入栈,否则弹出
                do {
                    opS = peek(Stack)->data[0];
                    int spriority,fpriority;
                    switch(opS){
                    //设置优先级
                    case '+':spriority=4;break;
                    case '-':spriority=4;break;
                    case '*':spriority=3;break;
                    case '/':spriority=3;break;
                    case '^':spriority=2;break;
                    case '(':spriority=7;break;
                    }
                    switch(opF){
                    case '+':fpriority=4;break;
                    case '-':fpriority=4;break;
                    case '*':fpriority=3;break;
                    case '/':fpriority=3;break;
                    case '^':fpriority=2;break;
                    case '(':spriority=7;break;
                    }
                    if (fpriority >= spriority)
                        add(postfix,pop(Stack));
                    else
                        break;
                } while (getLength(Stack) != 0);
                push(Stack,get(infix,i));
            }
        }
    }
    while (getLength(Stack) != 0)
        add(postfix,pop(Stack));
//释放括号占用的内存
    for(int i=0;i<getLength(infix);i++){
        NODE temp=get(infix,i);
        if(temp->data[0]=='(' || temp->data[0]==')'){
            free(temp->data);
            free(temp);
        }
    }
    //释放栈占用的内存
    del(Stack);
    //释放掉前缀表达式占用的内存
    del(infix);
    return postfix;
}

//生成表达式树
Bitree postfix_to_binarytree(mystable postfix)
{
    mystack Stack=initial();
    for (int i = 0; i < getLength(postfix); i++) {
        char name;
        name=get(postfix,i)->data[0];
        if ((name>='0' && name<='9') || name=='.' || (name>='a' && name<='z')){
            push(Stack,get(postfix,i));
        }else{
            NODE parent=get(postfix,i);
            NODE lchild,rchild;
            //从栈中弹出操作数,将运算符节点的两个儿子指针指向操作数结点
            if(getLength(Stack)!=0){
                rchild=pop(Stack);
                parent->rchild=rchild;
            }
            if(getLength(Stack)!=0){
                lchild=pop(Stack);
                parent->lchild=lchild;
            }
            push(Stack,parent);
        }
    }
    if(getLength(Stack)!=1){
        return NULL;
    }else{
        NODE result=pop(Stack);
        //释放内存
        free(Stack);
        free(postfix);
        return result;
    }
}

//打印前缀表达式
void print_prefix(Bitree node)
{
    if(node==NULL)
        return;
    fprintf(wfile,"%s",node->data);
    if(node->lchild!=NULL)
        print_prefix(node->lchild);
    if(node->rchild!=NULL)
        print_prefix(node->rchild);
}

//打印后缀表达式
void print_postfix(Bitree node)
{
    if(node==NULL)
        return;
    if(node->lchild!=NULL)
        print_postfix(node->lchild);
    if(node->rchild!=NULL)
        print_postfix(node->rchild);
    fprintf(wfile,"%s",node->data);
}



//递归打印叶节点递归函数入口
void _print_path_with_recursion(Bitree tree,NODE path[],int depth)
{
    if(tree==NULL)
        return;
    //若为叶节点则打印路径
    if(tree->lchild==NULL && tree->rchild==NULL){
        fprintf(wfile,"%s : %s",tree->data,tree->data);
        for(int i=depth-1;i>=0;i--)
            fprintf(wfile," %s",path[i]->data);
        fprintf(wfile,"%s
","");
    }
    if(tree->lchild!=NULL){
        path[depth]=tree;
        _print_path_with_recursion(tree->lchild,path,depth+1);
    }
    if(tree->rchild!=NULL){
        path[depth]=tree;
        _print_path_with_recursion(tree->rchild,path,depth+1);
    }
}

//非递归打印叶节点
void print_path_without_recursion(Bitree tree)
{
    NODE curr=tree;
    NODE path[100];
    //存放深度的数组
    int depth[100];
    int top=0,curdepth=0;

    mystack track=initial();
    do{
        if(curr!=NULL){
            if(curr->lchild==NULL && curr->rchild==NULL){
                fprintf(wfile,"%s : %s",curr->data,curr->data);
                for(int i=curdepth-1;i>=0;i--)
                    fprintf(wfile," %s",path[i]->data);
                fprintf(wfile,"%s
","");
                //从栈中弹出下一个要访问的结点,并将当前深度更新为该结点深度
                curr=pop(track);
                curdepth=depth[--top];
            }else{
                path[curdepth]=curr;
                push(track,curr->rchild);
                depth[top++]=++curdepth;
                curr=curr->lchild;
            }
        }else{
            curr=pop(track);
            curdepth=depth[--top];
        }
    }while(curr!=NULL || getLength(track)!=0);
}
//递归打印叶节点主程序入口
void print_path_with_recursion(Bitree tree)
{
    NODE path[100];
    _print_path_with_recursion(tree,path,0);
}
int main(){
    char ch[100];
    int icase=1;
    while(fscanf(rfile,"%s",ch),strcmp(ch,"no")!=0)//输入表达式
  {
    fprintf(wfile,"%s%d%s

","案例 #",icase++,": ");
    mystable infix=char_to_infix(ch);
    mystable postfix=infix_to_postfix(infix);
    Bitree root=postfix_to_binarytree(postfix);
    if(root==NULL)
        fprintf(wfile,"%s","输入有误!

");
    else{
        fprintf(wfile,"%s","输出前缀表达式:  ");
        print_prefix(root);//输出前缀式
        fprintf(wfile,"%s

","");
        fprintf(wfile,"%s","输出后缀表达式:  ");
        print_postfix(root);//输出后缀式2
        fprintf(wfile,"%s

","");
        fprintf(wfile,"%s
","用递归打印从根节点到叶子节点的路径:");
        print_path_with_recursion(root);
        fprintf(wfile,"%s
","");
        fprintf(wfile,"%s
","用非递归打印从根节点到叶子节点的路径:");
        print_path_without_recursion(root);
    }
 }
    return 0;
}
View Code

任务(3):

对于拓扑排序,我用了两种方法,一种是利用邻接矩阵:

#include"iostream"
#include"stdio.h"
#include"cmath"
#include"string.h"
#include"queue"
#include"stack"
#include"vector"
#include"algorithm"
#include"fstream"
using namespace std;
const int mx=105;
const int inf=32767;//表示无穷大
FILE* rfile=fopen("E:\read6.txt","r");
FILE* wfile=fopen("E:\write6.txt","w");
int n,m;;//n表示节点的数目,m表示边的数目
int topoArray[mx];//拓扑排序的数组
bool visited[mx];//用来标记该顶点是否已被访问过
bool cnt[mx];//用于拓扑排序中判断某个点是否已进栈
struct Mgraph//图的邻接矩阵
{
    int NumVertices,NumEdges;
    int Edges[mx][mx];
};
struct EdgeNode//邻接表的边节点类型
{
    int dest;//边的另一顶点位置
    int weight;//边的权重
    EdgeNode *link;//下一条链指针
};
struct VertexNode//顶点节点类型(表头节点)
{
    int data;
    EdgeNode *first;
};
struct ALGraph//邻接表类型
{
    VertexNode verticeslish[mx];
    int NumVetices,NumEdeges;
};
//创建图的邻接矩阵表示
void Creat_Mgraph(Mgraph &M)
{
        int i;
        M.NumVertices=n;
        M.NumEdges=m;
        //初始化所有边之间的权值为-1,表示两个结点之间无直接通路
        memset(M.Edges,-1,sizeof(M.Edges));
        for(i=0;i<m;i++)
        {
            int p,q,w;
            fscanf(rfile,"%d%d%d",&p,&q,&w);
            M.Edges[p][q]=w;
        }
}
//将邻接矩阵转换为邻接表表示
void Mgraph_to_ALGraph(Mgraph &M,ALGraph &ALG)
{
    ALG.NumVetices=M.NumVertices;
    ALG.NumEdeges=M.NumEdges;
    int i,j;
    for(i=0;i<n;i++)
    {
        ALG.verticeslish[i].data=i;
        ALG.verticeslish[i].first=NULL;
        for(j=0;j<n;j++)
        {
            if(M.Edges[i][j]!=-1)
            {
                EdgeNode  *temp=new EdgeNode;
                temp->link=ALG.verticeslish[i].first;
                temp->weight=M.Edges[i][j];
                temp->dest=j;
                ALG.verticeslish[i].first=temp;
            }
        }
    }
}
//输出图的邻接矩阵表示
void Output_Mgraph(Mgraph &M)
{
    int i,j;
    for(i=0;i<M.NumVertices;i++)
    {
        fprintf(wfile,"%d%s",i,": ");
        for(j=0;j<M.NumVertices;j++)
        {
            fprintf(wfile,"%d%s",M.Edges[i][j]," ");
        }
        fprintf(wfile,"%s
","");
    }
     fprintf(wfile,"%s
","");
}
//输出图的邻接表表示
void Output_ALGraph(ALGraph &ALG)
{
     int i;
     for(i=0;i<ALG.NumVetices;i++)
     {
         int flag=false;
         fprintf(wfile,"%d%s",i,": ");
         EdgeNode *temp;
         temp=ALG.verticeslish[i].first;
         while(temp!=NULL)
         {
             flag=true;
             fprintf(wfile,"%d%s%d%s",temp->dest,"(",temp->weight,")  ");
             temp=temp->link;
         }
         if(!flag) fprintf(wfile,"%s
","");
         fprintf(wfile,"%s
","");
     }
}
//用dfs递归遍历从0开始的深度优先遍历序列
void Dfs_From_0(int k,ALGraph &ALG)
{
    if(!visited[k])
    {
        fprintf(wfile,"%d%s",k," ");
        visited[k]=true;
        EdgeNode *temp=ALG.verticeslish[k].first;
        while(temp!=NULL)
        {
            Dfs_From_0(temp->dest,ALG);
            temp=temp->link;
        }
    }
}
//从0开始的广度优先遍历非递归算法
void Bfs_From_0(int k,ALGraph &ALG)
{
    memset(visited,false,sizeof(visited));
    fprintf(wfile,"%d%s",k," ");
    visited[k]=true;
    EdgeNode *temp=ALG.verticeslish[k].first;
    queue<EdgeNode *>q;
    while(temp!=NULL)
    {
        if(!visited[temp->dest])
            {q.push(temp);visited[temp->dest]=true;}
            temp=temp->link;
    }
    EdgeNode *cur;
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        k=cur->dest;
        fprintf(wfile,"%d%s",k," ");
        cur=ALG.verticeslish[k].first;
        while(cur!=NULL)
        {
            if(!visited[cur->dest])
            {q.push(cur);visited[cur->dest]=true;}
            cur=cur->link;
        }
    }
}
//判断某个节点是否入度为零
bool Judge_Column(Mgraph &M,int k)
{
    int i;
    for(i=0;i<M.NumVertices;i++)
    {
        if(M.Edges[i][k]!=-1)
        {
            return false;
        }
    }
    return true;
}
//输出拓扑排序的结果
void Output_Topoarray(Mgraph &M,int k)
{
    if(k<M.NumVertices)
        fprintf(wfile,"%s
","图中有有向环!");
    else
    {
        fprintf(wfile,"%s","输出该图的拓扑序列: ");
        for(int i=0;i<k;i++)
            fprintf(wfile,"%d%s",topoArray[i]," ");
    }
    fprintf(wfile,"%s
","");
}
//进行拓扑排序
void TopologicalSort(Mgraph &M)
{
    memset(cnt,false,sizeof(cnt));
    stack<int>S;
    int k=0,i,j;
    for(i=0;i<M.NumVertices;i++)
    {
        if(Judge_Column(M,i)&&!cnt[i])
        {
            cnt[i]=true;
            topoArray[k++]=i;
            S.push(i);
        }
    }
    while(!S.empty())
    {
        int cur=S.top();
        S.pop();
        for(j=0;j<M.NumVertices;j++)
            M.Edges[cur][j]=-1;
        for(i=0;i<M.NumVertices;i++)
       {
         if(Judge_Column(M,i)&&!cnt[i])
         {
            cnt[i]=true;
            topoArray[k++]=i;
            S.push(i);
          }
       }
    }
    Output_Topoarray(M,k);
}

int main()
{
    int iCase=1;//案例个数
    Mgraph M;
    ALGraph ALG;
    while(fscanf(rfile,"%d%d",&n,&m),n&&m)
    {
         fprintf(wfile,"%s%d%s
","案例 #",iCase++,": ");
         Creat_Mgraph(M);
         Mgraph_to_ALGraph(M,ALG);
         fprintf(wfile,"%s
","输出图的邻接矩阵表示:");
         Output_Mgraph(M);
         fprintf(wfile,"%s
","输出图的邻接表表示:");
         Output_ALGraph(ALG);
         memset(visited,false,sizeof(visited));
         fprintf(wfile,"%s","输出从0开始的递归dfs遍历:");
         Dfs_From_0(0,ALG);
         fprintf(wfile,"%s
","");
         fprintf(wfile,"%s","输出从0开始的非递归bfs遍历: ");
         Bfs_From_0(0,ALG);
         fprintf(wfile,"%s
","");
         TopologicalSort(M);
         fprintf(wfile,"%s
","");
    }
    return 0;
}
View Code

一种是利用邻接表:

#include <stdio.h>
#include <stdlib.h>
#include <Queue>
#include <string.h>
#include <Stack>
using namespace std;
bool visit[1000];
int inCount[1000];

typedef struct EdgeNode{
      int dest;
      int cost;
      struct EdgeNode *Link;
};
typedef struct VertexNode
{
      int data;
      struct EdgeNode *first;
};
typedef struct ALGraph
{
      VertexNode *VerticesList;
      int numVertices,numEdges;
};
void InitGraph(ALGraph& G)
{
      G.numVertices=0;
      G.numEdges=0;
      G.VerticesList=new VertexNode[1000];
      for (int i=0;i<1000;i++)
      {
            G.VerticesList[i].first=NULL;
      }
};
int GetVertexPos(ALGraph& G,int vertex)/*找出该顶点的顶点号*/
{
      for (int i=0;i<G.numVertices;i++)
            if (G.VerticesList[i].data==vertex)
                  return i;
      return -1;
}
int GetValue(ALGraph& G,int i)/*返回顶点i,不合理则返回0*/
{
      if (i==-1)
            return 0;
      else
            return G.VerticesList[i].data;
};
int FirstNeighbor(ALGraph& G,int v)/*返回顶点v的第一个邻接顶点的顶点号,若无则返回-1*/
{
      if (v!=-1)
      {
            EdgeNode *p=G.VerticesList[v].first;
            if (p!=NULL)
                  return p->dest;
      }
      else return -1;
}

int NextNeighbor(ALGraph &g, int v, int w)/*返回在顶点v的邻接顶点w后的下一个顶点号,没有则返回-1*/
{
    EdgeNode *p;
    p=g.VerticesList[v].first;
    while(p)
    {
        if(p->dest==w&&p->Link!=NULL)
            return p->Link->dest;
        p=p->Link;
    }
    return -1;
}

void creat(ALGraph& G)
{
      int i,j,k;
      EdgeNode *s;
      int n,m;
      int weight;
      printf("请输入顶点数和边数:
");
      scanf("%d %d",&G.numVertices,&G.numEdges);
      printf("输入顶点信息:
");
      for (i=0;i<G.numVertices;i++)
      {
            scanf("%d",&G.VerticesList[i].data);
            G.VerticesList[i].first=NULL;
      }
      printf("输入边的信息:
");
      for (k=0;k<G.numEdges;k++)
      {
            scanf("%d %d %d",&i,&j,&weight);
            s=new EdgeNode;
            s->dest=j;
            inCount[j]++;
            s->cost=weight;
            s->Link=G.VerticesList[i].first;

            G.VerticesList[i].first=s;
      }

}

int Numberofvertices(ALGraph& G)/*返回图中的顶点个数*/
{
      return G.numVertices;
}
void PrintfGraph(ALGraph& G)/*输出有向图邻接表*/
{
      int i,j;
      EdgeNode *p;
      printf("图G的顶点数是:%d
",G.numVertices);
      printf("顶点向量的值是:");
      for (i=0;i<G.numVertices;i++)
            printf("%d  ",G.VerticesList[i].data);
      printf("
");
      printf("图G的边数是:%d
",G.numEdges);
      for (i=0;i<G.numVertices;i++){
            for (p=G.VerticesList[i].first;p!=NULL;p=p->Link)
                  printf("(%d,%d,%d)
",i,p->dest,p->cost);
      }
};
void DFS(ALGraph& G,int v,bool visited[])/*DFS*/
{
      printf("%d  ",GetValue(G,v));
      visited[v]=true;
      int w=FirstNeighbor(G,v);
      while (w!=-1)
      {
            if (visited[w]==false)
                  DFS(G,w,visited);
            w=NextNeighbor(G,v,w);
      }
};


void BFS(ALGraph&G, int v)/*BFS*/
{
      int i,k,w,n=Numberofvertices(G);
      for (i=0;i<n;i++)
            visit[i]=false;
      queue <int > q;/*创建队列*/
      if (!visit[v])
      {
            printf("%d  ",G.VerticesList[v].data);
            visit[v]=true;
      }
      q.push(v);
      while (!q.empty())
      {
            int vv=q.front();
            q.pop();
            for (int w = FirstNeighbor(G, vv); w >= 0; w = NextNeighbor(G, vv, w))
            {
                  if (!visit[w])
                  {
                        printf("%d  ",G.VerticesList[w].data);
                        visit[w] = true;
                        q.push(w);
                  }
            }
      }
      delete[]visit;
};
void TopologicalSort(ALGraph& g)//拓扑排序算法
{

    stack<int> s;
    for(int i=1;i<=g.numVertices;i++)
        if(!inCount[i])
            s.push(g.VerticesList[i].data);//入度为0者进栈
    int count=0;
    while(!s.empty())
    {
        int v = s.top();
        s.pop();
        printf("%d  ",v);
        count++;
        for(EdgeNode *p = g.VerticesList[v].first ; p!=NULL ; p=p->Link)
        {
            //对i号顶点的每个邻接点的入度减1,新产生的入度为0的顶点进栈
            int k = p->dest;
            if(!(--inCount[g.VerticesList[k].data]))
                  s.push(g.VerticesList[k].data);
        }
    }
    printf("
")
    if(count<g.numVertices)
      printf("存在回路
");
    else
      printf("存在拓扑排序
");
}


int main()
{
      int start;
      int i,j;
      ALGraph G;
      InitGraph(G);
      creat(G);
      PrintfGraph(G);
      TopologicalSort(G);
      printf("输入从哪个点开始DFS遍历:
");
      scanf("%d",&start);
      DFS(G,start,visit);
      printf("
");
      printf("输入从哪个点开始BFS遍历:
");
      scanf("%d",&start);
      BFS(G,start);
      printf("
");

      return 0;
}
/*
5 7
0 1 2 3 4
0 1 10
1 2 50
0 4 100
0 3 30
2 4 10
3 2 20
3 4 60
*/
View Code

 实验六:

1、顺序查找和二分查找

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"string"
#include"fstream"
#include"cmath"
#include"queue"
#include"stack"
#include"vector"
using namespace std;
const int mx=1005;
FILE* rfile=fopen("E:\read7.txt","r");
FILE* wfile=fopen("E:\write7.txt","w");

struct SeqList //顺序表的数据结构
{
    int DataNum;
    int data[mx];
};
//顺序查找
int SeqFind(SeqList &L,int x)
{
    int step=1;
    L.data[L.DataNum]=x;//监视哨
    for(int i=0;i<=L.DataNum;i++)
    {
        fprintf(wfile,"%s%d%s%d %d
","",step++," 步查找到的值和下标分别为:",L.data[i],i);
        if(x==L.data[i]) return i;
    }
}
//二分查找
int BinFind(SeqList &L,int x)
{
    int step=1;
    int mid,left,high;
    left=0;high=L.DataNum-1;
    while(left<=high)
    {
         mid=(left+high)/2;
         fprintf(wfile,"%s%d%s%d %d
","",step++," 步查找到的值和下标分别为:",L.data[mid],mid);
         if(L.data[mid]==x)
            return mid;
         else if(x<L.data[mid])
            high=mid-1;
         else
            left=mid+1;
    }
    return L.DataNum;
}
int main()
{
    int iCase=1;//案例个数
    int num;//元素个数;
    int i,j,FindNum;//FindNum为查找返回的下标
    while(fscanf(rfile,"%d",&num),num!=0)
    {
        fprintf(wfile,"%s%d%s
","案例 #",iCase++,": ");
        SeqList L;
        L.DataNum=num;
        fprintf(wfile,"%s","输出原始序列: ");
        for(i=0;i<num;i++)
            {fscanf(rfile,"%d",&L.data[i]);fprintf(wfile,"%d ",L.data[i]);}
        fprintf(wfile,"%s
","");
        fscanf(rfile,"%d",&FindNum);
        fprintf(wfile,"%s%d

","需要查找的数(顺序查找): ",FindNum);
        fprintf(wfile,"%s
","输出查找过程: ");
        int FindResult=SeqFind(L,FindNum);
           fprintf(wfile,"%s
","输出查找结果: ");
        if(FindResult==L.DataNum)
            fprintf(wfile,"%s%d%s

","原序列中不存在 ",FindNum,"!");
        else
            fprintf(wfile,"%d%s%d

",FindNum," 在原序列中的下标为: ",FindResult);
        sort(L.data,L.data+L.DataNum);
        fprintf(wfile,"%s","将上面的序列排好序输出: ");
        for(i=0;i<num;i++)
            fprintf(wfile,"%d%s",L.data[i]," ");
        fprintf(wfile,"%s

","");
        fprintf(wfile,"%s%d

","需要查找的数(折半查找): ",FindNum);
        FindResult=BinFind(L,FindNum);
        fprintf(wfile,"%s
","输出查找结果: ");
        if(FindResult==L.DataNum)
            fprintf(wfile,"%s%d%s

","新序列中不存在 ",FindNum,"!");
        else
            fprintf(wfile,"%d%s%d

",FindNum," 在新序列中的下标为: ",FindResult);
    }
    return 0;
}
View Code

2、直接插入排序 

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"string"
#include"cmath"
#include"queue"
#include"stack"
#include"vector"
#include"fstream"
using namespace std;
const int mx=1005;
//输出序列
void Output_Array(int Array[],int Num)
{
    int i;
    for(i=0;i<Num;i++)
        printf("%d ",Array[i]);
    printf("
");
}
//直接插入排序
void Straight_Insertion_Sort(int Array[],int Num)
{
    int i,j;
    for(i=1;i<Num;i++)
    {
        if(Array[i]<Array[i-1])
        {
            int temp=Array[i];
            for(j=i-1;j>=0&&Array[j]>temp;j--)
            {
                Array[j+1]=Array[j];
            }
            Array[j+1]=temp;
        }
        printf("第%d次进行插入排序得到的序列: ",i);
        Output_Array(Array,Num);
    }
}

int main()
{
    int iCase=1;
    freopen("E:\read8.txt","r",stdin);
    freopen("E:\write8.txt","w",stdout);
    int Array[mx];
    int i,j,Num;
    while(scanf("%d",&Num),Num!=0)
    {
        printf("案例 #%d :
",iCase++);
        for(i=0;i<Num;i++)
            scanf("%d",&Array[i]);
        printf("原始序列:");
        for(i=0;i<Num;i++)
            printf("%d ",Array[i]);
        printf("
");
        Straight_Insertion_Sort(Array,Num);
    }
}
View Code

3、快速排序

#include"iostream"
#include"stdio.h"
#include"algorithm"
#include"string.h"
#include"string"
#include"cmath"
#include"queue"
#include"stack"
#include"vector"
#include"map"
using namespace std;
const int mx=1005;
int step;//记录快速排序进行的步数
int num;//记录序列中元素的个数
void Quick_Sort(int Array[],int low,int high)
{
    if(low>=high) return;
    int first=low;
    int last=high;
    int key=Array[first];
    while(first<last)//将比key小的放到key前面,比key大的放到key后面
    {
        while(first<last&&Array[last]>=key) last--;
        Array[first]=Array[last];
        while(first<last&&Array[first]<=key) first++;
        Array[last]=Array[first];
    }
    Array[first]=key;
    printf("第 %d 次排序后的序列: ",step++);//输出序列
    for(int  i=0;i<num;i++)
        printf("%d ",Array[i]);
    printf("
");
    Quick_Sort(Array,low,first-1);//分治的思想
    Quick_Sort(Array,first+1,high);
}
int main()
{
    int i,iCase=1;
    int Array[mx];
    freopen("E:\read9.txt","r",stdin);
    freopen("E:\write9.txt","w",stdout);
    while(scanf("%d",&num),num!=0)
    {
        step=1;
        printf("案例 #%d : 
",iCase++);
        for(i=0;i<num;i++)
            scanf("%d",&Array[i]);
        printf("进行快速排序:
");
        Quick_Sort(Array,0,num-1);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/acm-jing/p/4443442.html