数据结构(严版)课本代码重敲——第七章

数据结构 第七章 图

四种基本存储结构之邻接矩阵表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/

/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#define INFINITY INT_MAX


using namespace std;
// 数组表示法/邻接矩阵表示法
const int MAXSIZE = 20;
typedef char vertexType;
typedef int vrType;
typedef char infoType;
typedef enum{DG,DN,UDG,UDN} graphKind;

typedef struct arcCell
{
    vrType adj;
    infoType *info;
}arcCell,adjMatrix[MAXSIZE][MAXSIZE];

typedef struct
{
    vertexType vex[MAXSIZE];
    adjMatrix arc;
    int vexnum,arcnum;
    graphKind kind;
}MGraph;

int locate(MGraph &g,vertexType v)
{
    for (int i=0;i<g.vexnum;i++)
    {
        if( g.vex[i] == v)
            return i;
    }
    return -1;
}
void createUDN(MGraph &g)
{
    int hasInfo;
    cout << "顶点数、边数、是否有信息"<<endl;
    cin >> g.vexnum >>g.arcnum >> hasInfo;
    int i,j;
    for (i=0;i<g.vexnum;i++)
    {
        cin >>g.vex[i];
    }
    for (i=0;i<g.vexnum;i++)
        for (j=0;j<g.vexnum;j++)
    {
        g.arc[i][j].adj = INFINITY;
        g.arc[i][j].info = NULL;
    }
    vertexType v1,v2;
    vrType w;
    cout << "边:" <<endl;
    for (int k=0;k<g.arcnum;k++)
    {
        cin >>v1 >>v2>>w;
        i = locate(g,v1);
        j = locate(g,v2);
        g.arc[i][j].adj = w;
        if (hasInfo)
            cin >> g.arc[i][j].info;
        g.arc[j][i] = g.arc[i][j];
    }
}
void createGraph(MGraph &g)
{
    graphKind kind;
    cout << "graphkind"<<endl ;
    cin >> (int &)kind;
    switch(kind)
    {
        case UDN:createUDN(g);
    }
}
void printMatrix(MGraph &g)
{
    int i,j;
    for (i=0;i< g.vexnum ; i++)
    {
         for (j = 0 ;j<g.arcnum;j++)
    {
        if (g.arc[i][j].adj == INFINITY)
            cout << '#' << ' ';
        else
            cout << g.arc[i][j].adj <<' ';
    }
    cout <<endl;
    }

}
// 深度优先搜索
bool visited[MAXSIZE];

int firstAdjVex(MGraph &g,int v)
{
    // 邻接矩阵表示法中,点v的第一个邻接点,在矩阵中横着找不为无穷大的点
    int j;
    for (j = 0; j < g.vexnum ; j++)
    {
      if (g.arc[v][j].adj!=INFINITY)
        return j;
    }
    return -1;
}
int nextAdjVex(MGraph &g,int v,int w)
{
    // v的邻接点中在w之后的第一个邻接点
    int j;
    for (j = w+1;j<g.vexnum;j++)
    {
        if (g.arc[v][j].adj!=INFINITY)
            return j;
    }
    return -1;
}
void DFS(MGraph &g,int v)
{
    visited[v] = true; // 从V结点开始深度搜索
    cout << g.vex[v] << ' ';
    for (int w = firstAdjVex(g,v); w >= 0 ;w = nextAdjVex(g,v,w))
    {
        if (!visited[w])
            DFS(g,w);// 对未被访问过的邻接点递归调用DFS
    }
}
void DFSTraverse(MGraph &g)
{
    int i;
    for (i=0;i<g.vexnum;i++)
        visited[i] = false; // 初始化visited,均未被访问
    for (i=0;i<g.vexnum;i++) // 一次寻找后可能有仍旧未被访问的点
    {
        if (!visited[i])
            DFS(g,i);
    }

}
int main()
{
    MGraph g;
    createGraph(g);
   // printMatrix(g);
   DFSTraverse(g);

    return 0;
}


邻接表表示法
/*
* 范围:第七章 图
* 日期:2018/4/1
*/

/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>
#define INFINITY INT_MAX


using namespace std;

// 邻接表

const int MAXSIZE = 20;

typedef char vertexType;
typedef char infoType;
typedef enum{DG,UDG} graphKind;

typedef struct arcNode
{
    int adjvex;
    infoType *info;
    struct arcNode *nextarc;
}arcNode;

typedef struct
{
    vertexType data;
    struct arcNode *firstarc;
}VNode;

typedef struct
{
    VNode adjList[MAXSIZE];
    int vexnum,arcnum;
    graphKind kind;
}ALGraph;

int locate(ALGraph &g,vertexType v)
{
    int i;
    for (i = 0;i<g.vexnum;i++)
    {
        if ( g.adjList[i].data == v )
            return i;
    }
    return -1;
}

void createUDG(ALGraph &g)
{
    int hasInfo;
    cout << "顶点数、边数、是否有信息"<<endl;
    cin >> g.vexnum >> g.arcnum>>hasInfo;
    int i,j,k;
    cout << "头结点" <<endl;
    for (i=0;i<g.vexnum;i++)
    {
        cin >> g.adjList[i].data ;
        g.adjList[i].firstarc = NULL;
    }
    vertexType v1,v2;
    arcNode *p,*q;
    cout << "边:" <<endl;
    for (k = 0; k < g.arcnum;k++)
    { // 头插法建立链表
        cin >> v1 >> v2;
        i = locate(g,v1);
        j = locate(g,v2);
        p = (arcNode*)malloc(sizeof(arcNode));
        if (hasInfo)
            cin >> p->info;
        p->adjvex = j;
        p->nextarc = g.adjList[i].firstarc;
        g.adjList[i].firstarc = p;

        // 无向图一条边建立两个节点
        q = (arcNode*)malloc(sizeof(arcNode));
        if (hasInfo)
            q->info = p->info;
        q->adjvex = i;
        q->nextarc = g.adjList[j].firstarc;
        g.adjList[j].firstarc = q;
    }
}

void createDG(ALGraph &g)
{
    int hasInfo;
    cout << "顶点数、弧数、有无信息"<<endl;
    cin >>g.vexnum >>g.arcnum >> hasInfo;

    int i,j,k;
    cout << "顶点" <<endl;
    for (i=0;i<g.vexnum;i++)
    {
        cin >> g.adjList[i].data;
        g.adjList[i].firstarc = NULL;
    }
    arcNode *p;
    vertexType v1,v2;
    cout << "弧" <<endl ;
    for (k = 0;k<g.arcnum;k++)
    {
        cin >>v1>>v2;
        i = locate(g,v1);
        j = locate(g,v2);
        p = (arcNode*)malloc(sizeof(arcNode));
        p->adjvex = j;
        p->nextarc = g.adjList[i].firstarc;
        if (hasInfo)
            cin >> p->info;
        g.adjList[i].firstarc = p;
    }


}

void buildNALG(ALGraph &g,ALGraph &ng)
{
    ng.vexnum = g.vexnum;
    ng.arcnum  = g.arcnum;

    int i,j;
    for (i=0;i<ng.vexnum;i++)
    {
        ng.adjList[i].data = g.adjList[i].data;
        ng.adjList[i].firstarc = NULL;
    }
    arcNode *p,*q;
    for (i = 0;i<g.vexnum;i++)
    {
        for (j = 0;j<g.vexnum;j++)
        {
            if (i==j)
                continue;
            p = g.adjList[j].firstarc;
            while (p)
            {
                if (p->adjvex == i)
                {
                    q = (arcNode *)malloc(sizeof(arcNode));
                    q->adjvex = j;
                    q->info = p->info;
                    q->nextarc = ng.adjList[i].firstarc;
                    ng.adjList[i].firstarc = q;
                }
                p = p->nextarc;
            }

        }
    }
}

void createGraph(ALGraph &g)
{
    graphKind kind;
    cout << "kind:"<<endl;
    cin >> (int &)kind;
    switch(kind)
    {
        case UDG:createUDG(g);break;
        case DG:createDG(g);
    }
}
void printGraph(ALGraph &g)
{
    int i;
    arcNode *p;
    for (i=0;i<g.vexnum;i++)
    {
        if (!g.adjList[i].firstarc)
            cout <<g.adjList[i].data << "->NULL";
        else
            cout << g.adjList[i].data <<"->";
        p = g.adjList[i].firstarc;
        while (p)
        {
            if (!p->nextarc)
                cout <<p->adjvex;
            else
                cout <<p->adjvex << "->";
            p = p->nextarc;
        }
        cout <<endl;
    }

}
// 深度优先搜索
bool visited[MAXSIZE];

int firstAdjVex(ALGraph &g,int v)
{
    if (g.adjList[v].firstarc)
        return g.adjList[v].firstarc->adjvex;
    else
        return -1;
}
int nextAdjVex(ALGraph &g,int v,int w)
{
    arcNode *p;
    p = g.adjList[v].firstarc;
    for (p ; p ; p = p ->nextarc)
    {
        if (p->adjvex == w)
        {
            if (p->nextarc)
            {
                return p->nextarc->adjvex;
            }
            else
                return -1;
        }
    }
}
void DFS(ALGraph &g,int v)
{
    visited[v] = true;
    cout << g.adjList[v].data<<' ';
    for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w)) // 注意这里不能写w,因为我的return值是-1!所以条件亦成立
    {
        if (!visited[w])
            DFS(g,w);
    }
}
void DFSTraverse(ALGraph &g)
{
    int i;
    for (i=0;i<g.vexnum;i++)
    {
        visited[i] = false;
    }
    for (i = 0;i<g.vexnum;i++)
    {
        if (!visited[i])
            DFS(g,i);
    }
}

// 广度优先搜索
void BFSTraverse(ALGraph &g)
{
    for (int i = 0;i<g.vexnum;i++)
        visited[i] = false;
    queue<int> que;
    for (int i = 0;i<g.vexnum;i++)
    {
        if (!visited[i])
        {
            visited[i] = true;
            cout << g.adjList[i].data<<' ';
            que.push(i);
            while (!que.empty())
            {
                int u = que.front();
                que.pop();
                for (int w = firstAdjVex(g,u) ; w >=0 ;w= nextAdjVex(g,u,w))
                {
                    if (!visited[w])
                    {
                        visited[w] = true;
                        cout << g.adjList[w].data <<' ';
                        que.push(w);
                    }
                }
            }
        }
    }
}
int main()
{
   ALGraph g,ng;
   createGraph(g);
   //buildNALG(g,ng);
   printGraph(g);
   DFSTraverse(g);


    return 0;
}

####十字链表表示法

/*
* 范围:第七章 图
* 日期:2018/4/1
*/

/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>


using namespace std;
// 十字链表
const int MAXSIZE = 20;

typedef char vertexType;
typedef char infoType;

typedef struct arcNode
{
    int tailvex,headvex;//尾部邻接点和头部邻接点
    struct arcNode *hlink,*tlink;//hlink指向弧头相同的下一条弧
    infoType *info;
}arcNode;

typedef struct
{
    vertexType data;
    struct arcNode *firstin,*firstout;
}VNode;

typedef struct
{
    int vexnum,arcnum;
    VNode olist[MAXSIZE];
}OLGraph;

int locate(OLGraph &g,vertexType v)
{
    int i;
    for (i=0;i<g.vexnum;i++)
    {
        if ( g.olist[i].data == v )
            return i;
    }return -1;
}
void createDG(OLGraph &g)
{
    cout << "顶点数、弧数、有无信息" << endl;
    int hasInfo;
    cin >> g.vexnum >>g.arcnum >> hasInfo;
    int i,j,k;
    cout << "顶点:" << endl;
    for (i=0;i<g.vexnum;i++)
    {
        cin >> g.olist[i].data;
        g.olist[i].firstin = NULL;
        g.olist[i].firstout = NULL;
    }
    cout << "弧:"<<endl;
    vertexType v1,v2;
    arcNode *p;
    for (k = 0;k<g.arcnum;k++)
    {
        cin >> v1 >> v2;a
        i = locate(g,v1);
        j = locate(g,v2);
        p->tailvex = i;
        p->headvex = j;
        if (hasInfo)
            cin >> p->info;
        p->tlink = g.olist[i].firstout;
        g.olist[i].firstout = p;
        // 至此完成邻接表的工作,十字链表即为邻接表+逆邻接表的结合体
        p->hlink = g.olist[j].firstin;
        g.olist[j].firstin = p;
    }
}
int main()
{



    return 0;
}

####邻接多重表表示法

/*
* 范围:第七章 图
* 日期:2018/4/1
*/

/*
笔记:
enum < 枚举类型名> {< 枚举表>};
enum day {Sun,Mon,Tue,Wed,Thu,Fri,Sat};
day d1,d2,d3;
d1 = Thu; d2 = Sat; d3 = Tue;
定义为枚举类型的变量,只能取枚举表中的值,枚举的本质是整型类型。
*/
#include <iostream>
#include <string>
#include <stdlib.h>


using namespace std;
// 邻接多重表 无向图的存储形式
const int MAXSIZE = 20;
typedef char vertexType;

typedef struct eNode
{
    bool mark;
    int ivex,jvex;
    struct eNode *ilink,*jlink; // ilink 指向依附于ivex的边
}eNode;

typedef struct VNode
{
    vertexType data;
    struct eNode *firstedge;
}VNode;

typedef struct
{
    VNode adjmulist[MAXSIZE];
    int vexnum,edgenum;
}AMLGraph;

void createAMLGraph(AMLGraph &g)
{
    cout << "顶点数、边数、有无信息"<<endl;
    int hasInfo;
    cin >> g.vexnum >> g.edgenum >> hasInfo;

    int i,j,k;
    for (i=0;i<g.vexnum;i++)
    {
        cin >> g.adjmulist[i].data;
        g.adjmulist[i].firstedge = NULL;
    }

    eNode *p;
    vertexType v1,v2;
    for (k=0;k<g.edgenum;k++)
    {
        cin >> v1 >> v2;
        i = locate(g,v1);
        j = locate(g,v2);
        p = (eNode *)malloc(sizeof(eNode));
        p->ivex = i;
        p->jvex = j;
        p->ilink = g.adjmulist[i].firstedge;
        p->jlink = g.adjmulist[j].firstedge;
        g.adjmulist[i].firstedge = p;
        g.adjmulist[j].firstedge = p;
    }
}
int main()
{



    return 0;
}

无向图的连通分量和生成树
/*
* 7.4 知识点
* 1. 遍历无向图时,对于连通图,从任一顶点出发进行深度或广度优先搜索即可;对于非联通图则需要从
* 多个顶点出发进行搜索,每次获得的顶点序列则为各个连通分量的顶点集。
* 2. 连通图有深度优先生成树和广度优先生成树,即搜索的路径形成的树。
* 3. 非连通图每个连通分量均可形成一个生成树,即一个生成森林。
* 4. 除了二叉树外的没有叉数限制的树一般用孩子-兄弟表示法表示成方便遍历的二叉树形式。
* 5. 森林的树的根节点其实亦为兄弟,也可以用孩子-兄弟表示法来表示。
*/
// 无向图的深度优先生成森林(非连通图)

typedef char Elemtype;
typedef struct CSNode
{
    Elemtype data;
    struct CSNode *child,*sibling;
}CSNode,*CSTree;


void DFSTree(ALGraph &g,CSTree &t,int v)
{
    // 从v顶点开始深度搜索生成树
    visited[v] = true;
    cout <<g.adjList[v].data << ' ';
    CSTree p,q;
    bool isfirst = true;
    for (int w = firstAdjVex(g,v) ; w>=0 ; w = nextAdjVex(g,v,w))
    {
        if (!visited[w])
        {
         p = (CSTree)malloc(sizeof(CSNode));
         p->data = g.adjList[w].data;
         p->child = NULL;
         p->sibling = NULL;
         // 创建新节点P作为根节点T的邻接点,但必须确定是第一个邻接点还是其他
         if (isfirst)
         {
             t->child = p;
             isfirst = false;
         }else
         {
             q->sibling = p;
         }
         q = p;
         DFSTree(g,p,w); // 递归寻找p的邻接点们!

        }
    }
}
void DFSForest(ALGraph &g,CSTree &t)
{
    for (int i=0;i<g.vexnum;i++)
        visited[i] = false;
    CSTree p,q;
    for (int i=0;i<g.vexnum;i++)
    {
        if (!visited[i])
        {
            p = (CSTree)malloc(sizeof(CSNode));
            p->data = g.adjList[i].data;
            p->child = NULL;
            p->sibling = NULL;
            if (!t)
            {
                t = p; // 第一棵生成树
            }else
            {
                q->sibling = p; // 非第一棵生成树,则为上一棵生成树根节点的兄弟
            }
            q = p;
            DFSTree(g,p,i);// 从i顶点出发建立以p为根节点的生成子树
        }
    }


}
void level(CSTree &t)
{
    queue<CSTree> q;
    CSTree p;
    if (t) // 空树没有必要遍历了
    {
        q.push(t); // 根节点入队
        while (!q.empty())
        {
           p =  q.front(); // 弹栈一个元素
           q.pop();
            cout << p->data << ' ';

            if (p->child)
            {
                q.push(p->child);
            }
            if (p->sibling)
            {
                q.push(p->sibling);
            }
        }
    }
}
测试数据

3
13 13 0
ABCDEFGHIJKLM
A C
A F
A L
A B
B M
D E
G H
G K
G I
H K
J L
J M
M L

最小生成树 之 普利姆算法
struct
{
    vertexType adjvex;
    vrType lowcost;
}closedge[MAXSIZE];
// 辅助数组的意义:记录从U到V-U中具有最小代价的边

int locateVex(MGraph &g,vertexType v)
{
    int k = -1;
    for (int i = 0 ;i<g.vexnum;i++)
    {
        if (g.vex[i] == v)
            k = i;
            return k;
    }
    return k;
}

int minimum(MGraph &g)
{
    int min1 = INFINITY;
    int k = -1;

    for (int i = 0;i<g.vexnum;i++)
    {
        if ( closedge[i].lowcost != 0  )
        {
            if ( closedge[i].lowcost < min1 )
            {
                min1 = closedge[i].lowcost;
                k = i;
            }
        }
    }
    return k;
}

void miniSpanTree_prim(MGraph &g,vertexType u)
{

    int k = locate(g,u);
    for (int i=0;i<g.vexnum;i++)
    { // closedge 一开始并不包含K
        if (i != k )
        {
            closedge[i].adjvex = u;
            closedge[i].lowcost = g.arc[k][i].adj;  //不与u邻接的点的lowcost是INFINITY
        }
    }
    closedge[k].lowcost = 0; // 被选入U的顶点的权值均为0

    for (int i = 1;i<g.vexnum ;i++) // 选择g.vexnum -1此V-U中的顶点,直到U = V为止
    {
        // 选择最小的权值,把顶点加入到U中
        k = minimum(g); // 求出下一个结点K
        cout <<"( " <<closedge[k].adjvex<<" , "<<g.vex[k]<<" )" << endl;  // 打印找到的边
        closedge[k].lowcost = 0; // 把K划入U集合中
        // 更新closedge
        for (int j =  0;j<g.vexnum;j++)
        {
            if (g.arc[k][j].adj < closedge[j].lowcost)
            {
                closedge[j].adjvex = g.vex[k];
                closedge[j].lowcost = g.arc[k][j].adj;
            }
        }

    }
}

测试数据:

3
6 10 0
ABCDEF
A B 6
A D 5
A C 1
B C 5
B E 3
C D 5
C E 6
C F 4
D F 2
E F 6

拓扑排序

/*
有向无环图的介绍:
1. 有向无环图:描述含有公共子式的工具,实现对相同子式地共享,从而节省存储空间
2. 检查一个有向图是否存在环比无向图复杂。无向图:深度优先遍历过程中遇到已访问过的顶点的边则必定存在环;
有向图:这条回边有可能是指向深度优先生成森林中另一棵生成树顶点的弧。
解决:从某个顶点V出发的遍历,在DFS(V)结束之前出现一条从顶点U到顶点V的回边,有向图上必定存在环。
3. 有向无环图是描述一项工程或系统的进行过程的有效工具。工程可分为若干个活动,活动之间存在条件的约束。
人们关心:1)工程能否顺利完成 2)工程完成所必须的最短时间

拓扑排序:
1. 由某个集合上的一个偏序得到该集合的一个全序的过程
2. 解释:偏序是指集合中仅有部分成员之间可比较,而全序为集合中全体成员之间均可比较,全序即为拓扑有序
3. 由偏序定义得到拓扑有序的操作便是拓扑排序
4. 顶点表示活动,弧表示活动之间优先关系的有向图称为顶点表示活动的网AOV网,直接前驱和直接后继
5. 在AOV网中不应该出现有向环,因此检测有向网中是否存在环的方法是:构造顶点的拓扑排序序列,若网中的所有顶点都在拓扑有序序列中则必定不存在环。
6. 如何进行拓扑排序?在有向图中选择一个没有前驱的顶点且输出,删除该顶点和所有以它为尾的弧

*/
int indegree[MAXSIZE];
void findInDegree(ALGraph &g)
{
    ALGraph ng;
    buildNALG(g,ng);
    arcNode *p;
    int d = 0;
    for (int i=0;i<ng.vexnum;i++)
    {
        d = 0;
        p = ng.adjList[i].firstarc;
        while (p)
        {
            d ++ ;
            p = p->nextarc;
        }
        indegree[i] = d;
    }
//    for (int i=0;i<g.vexnum;i++)
//        cout <<indegree[i] <<  ' ';
}
int  topoLogicalSort(ALGraph &g)
{
    findInDegree(g); // 找到各定点的入度
    stack<int> st;
    // 把所有入度为0的顶点入栈
    for (int i  =0;i<g.vexnum;i++)
    {
        if (!indegree[i])
            st.push(i);
    }
    int i;
    arcNode *p;
    int count = 0 ; // 对输出顶点计数
    while (!st.empty())
    {
        i = st.top();
        st.pop();
        cout << g.adjList[i].data << ' ';
        count ++;
        for (p = g.adjList[i].firstarc ; p ; p=p->nextarc)
        {
            // 对I号顶点的每个邻接点的入度都减1
            int k = p->adjvex;
            if (!(--indegree[k]))
                st.push(k); // 若减1后变为入度为0,入栈
        }
    }
    if (count < g.vexnum)
        return -1;
    else
        return 1;
}
关键路径
int ve[MAXSIZE]; // 各顶点的最早开始时间
int vl[MAXSIZE]; // 各顶点的最迟开始时间

/* 
1. 计算各顶点的最早开始时间ve
2. T为拓扑序列顶点栈
3. S为零入度顶点栈
4. 若G无回路,则用栈T返回G的一个拓扑序列
*/
int topoLogicalOrder(ALGraph &g,stack<int> &t)
{
    findInDegree(g,indegree);
    stack<int> s;
    for (int i = 0;i<g.vexnum;i++)
    {
        if (!indegree[i])
            s.push(i);
    }
    int count =  0;
    for (int i=0;i<g.vexnum;i++)
        ve[i] = 0;
    while (!s.empty())
    {
        int j = s.top();
        s.pop();
        t.push(j);
        count ++ ;
        for (arcNode *p = g->adjList[j].firstarc ; p ; p = p->nextarc)
        {
            int k = p->adjvex;
            if (!(--indegree[k]))
                s.push(k);
            if (ve[j]+*(p->info) > ve[k])
                ve[k] = ve[j] + *(p->info);
        }
    }
    if (count <g.vexnum)
        return -1;
    else return 1;
}

// 关键路径
int criticalPath(ALGraph &g)
{
    // 目的:输出G的各项关键活动
    stack<int> t;
    arcNode *p;
    if (!topoLogicalOrder(g,t))
        return -1;
    for (int i=0;i<g.vexnum;i++)
        vl[i] = ve[g.vexnum-1] ; // 初始化均为最大值
    while (!t.empty())
    {
        int j = t.top();
        t.pop();
        for (p = g.adjList[j].firstarc ; p ; p= p->nextarc)
        {
            int k = p->adjvex;
            dut = *(p->info);
            if (vl[k]-dut < vl[j])
                vl[j] = vl[k] - dut;
        }
    }
    for (j = 0;j<g.vexnum;j++)
    {
        for (p = g.adjList[i].firstarc ; p;p=p->nextarc)
        {
            int k = p->adjvex;
            dut = *(p->info);
            int ee = ve[j];
            el = vl[k] - dut;
            tag = (ee == el) > 
            
        }
    }
    
      
    
}
最短路径-迪杰斯特拉
/* 最短路径
1. 交通路网上从原点A到达目的地B的所含边的数目最少的路径,只需要广度优先搜索,遇到B点时停止
2. 源点到其余各个顶点的最短路径--迪杰斯特拉算法--按照路径长度递增的次序产生最短路径的算法
3. 求从源点v0到其余各点v的最短路径P[v]和带权长度d[v]
4. p[v][w] == true, 则w是v0 - v 上最短路径的一个顶点,该路径显然经过v0 和 v\
5. final[v]为已经归入点集合的点
*/
bool p[MAXSIZE][MAXSIZE];
int d[MAXSIZE];
bool final[MAXSIZE];

void shortestPath(MGraph &g,int v0)
{

    for (int i=0;i<g.vexnum;i++)
    {
        final[i] = false;
        d[i] = g.arc[v0][i].adj;
        for (int j = 0;j<g.vexnum;j++)
            p[i][j] = false;

        if (d[i]!=INFINITY)
        {
            p[i][i] = true;
            p[i][v0] = true;
        }
    }
    final[v0] = true;
    d[v0] = 0;
    int v;
    int min = INFINITY;
    for (int i=1;i < g.vexnum;i++)
    { // 对其余的g.vexnum - 1个顶点,每次选择最短的一条路径的顶点加入final集合
        min = INFINITY;
        for (int j=0;j<g.vexnum;j++)
            if (!final[j])
            if (d[j] < min)
        {
            min = d[j];
            v = j; // v是此次选出的顶点
        }
        final[v] = true;
        // 更新最短路径及距离
        for (int j = 0;j<g.vexnum;j++)
        {
            if (!final[j] && d[j] > (g.arc[v][j].adj + min)) //此处注意INFINIT + INT 不会小于 INFINIT,因为已经到了能存储的最大数
            {
                d[j] = min + g.arc[v][j].adj;
                for (int k = 0;k<g.vexnum;k++)
                    p[j][k] = p[v][k];
                p[j][j] = true;
            }
        }
    }
}

void printShortestPath(MGraph &g)
{
    int i;
    for (i = 1;i<g.vexnum;i++)
    {
        cout << g.vex[i] << "\t"<<'(';
        for (int j = 0;j<g.vexnum;j++)
            if (p[i][j])
            cout << g.vex[j] <<' ' ;
        cout << ')'<<"\t" ;
        cout << d[i] <<endl;
    }
}
测试数据

// 迪杰特斯拉
1
6 8 0
ABCDEF
A C 10
A E 30
A F 100
B C 5
C D 50
E D 20
E F 60
D F 10

数据结构》(C语言版) 算法源码及运行演示系统使用说明 一、启动演示系统 双击演示系统应用程序文件“DS_VC_ALGO.EXE”启动演示系统,出现图1所示界面。 图1 《数据结构》(C语言版)算法源码及运行演示系统主界面 二、演示系统使用步骤 除了个别算法之外,演示系统给出了《数据结构》(C语言版)书中算法对应的程序代码(CPP文件)和测试运行程序(VC++6.0的EXE文件)。通过本系统,可以显示算法的源代码以及运行结果。具体操作步骤如下: 1.选择相应章 单击演示系统界面右侧章选择按钮。 例如,要选择第6章,则单击“第6章”选择按钮。 当相应章被选择后,窗口的右侧部分将列出本章的算法选择按钮。 例如,选择第6章后,窗口的右侧部分将显示第6章中的算法6.1-6.13和6.15的选择按钮。由于书中的算法6.14和6.16只是示意性算法,故未给出源码,其按钮上的文字为灰色,处于“无效”状态。 2.选择相应章中的算法 单击窗口右侧部分所列举的本章某个算法选择按钮,被选择的算法的源码将在窗口左侧空白区域中显示。对于较长的源码,单击显示区域后,可用键盘的光标键和翻页键浏览源码。 例如,选择了第6章中的算法6.5后界面如图2所示: 图2 选择算法6.5 3.运行测试程序 单击窗口上部的“运行”按钮,将弹出运行窗口,运行所选算法的测试程序。若运行按钮为灰色,表示该算法无单独测试程序。 例如,算法6.5的测试运行窗口如图3所示: 图3 测试运行窗口 测试运行说明: 测试运行窗口显示程序的执行过程及结果。若在显示过程中出现运行窗口无法正常演示的情况,只需调节运行窗口大小即可正常显示(调节最小化按钮或窗口最大化/还原按钮“ ”)。 三、退出演示系统 使用完毕后,单击窗口右上角关闭按钮“ ”退出演示系统。 四、测试程序示例 在《数据结构》的课程教学中,各抽象数据类型的设计与实现是重要的学习和实践环节。为此,本系统只给出了各算法源码的测试程序的可执行文件。在此,给出算法6.5的测试程序示例,以供参考。 算法6.5是中序遍历线索二叉树的非递归算法,要对其源码进行测试,可首先调用算法6.6及6.7建立中序线索二叉树。以下是测试程序的源码,相关类型和辅助函数定义在文件include06.h和include06.cpp中,此略。 // test0605.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "include06.h" // 相关类型和辅助函数的定义 BiThrTree pre; // 线索二叉树遍历辅助变量 #include "algo0607.cpp" // 算法6.7源码 #include "algo0606.cpp" // 算法6.6源码 #include "algo0605.cpp" // 算法6.5源码 int main(int argc, char* argv[]) { char gl_str[64]; BiThrTree T; BiThrTree Thrt; printf("*******************************************\n"); printf("* 《数据结构》(C语言版)严蔚敏,吴伟民 *\n"); printf("* 算法6.5, 6.6 & 6.7 *\n"); printf("*******************************************\n"); srand((unsigned)time(NULL)); // 随机函数初始化 T=NULL; // 空二叉树T for (int pass=0; pass<5; pass++) { // 测试运行5次,第一次为空树 outBiThrTree(T,gl_str); // 以类广义表的形式输出二叉树T到gl_str printf("T = %s\n", gl_str); // 显示 pre = NULL; Status r = InOrderThreading(Thrt, T); // 算法6.6,6.7,中序线索化 printf("InOrderThreading(Thrt, T) : %s\n", (r) ? "OK" : "ERROR"); initVisitStr(); // 将visitStr清为空串 InOrderTraverse_Thr(Thrt, v
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值