数据结构与算法--图的存储

212 阅读4分钟

1、邻接矩阵

#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXVEX 100 /* 最大顶点数,应由用户定义 */
#define INFINITYC 0

typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef char VertexType; /* 顶点类型应由用户定义  */
typedef int EdgeType; /* 边上的权值类型应由用户定义 */
typedef struct {
    VertexType vexs[MAXVEX]; /* 顶点表 */
    EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
    int numNodes, numEdges; /* 图中当前的顶点数和边数  */
}MGraph;

void CreateMGraph(MGraph *G) {
    int i,j,k,w;
    printf("输入顶点数和边数:\n");
    //1. 输入顶点数/边数
    scanf("%d,%d",&G->numNodes,&G->numEdges);
    printf("顶点数:%d,边数:%d\n",G->numNodes,G->numEdges);
    
    //2.输入顶点信息/顶点表
    for (i = 0; i<= G->numNodes;i++)
        scanf("%c",&G->vexs[i]);
    
    //3.初始化邻接矩阵
    for (i = 0; i < G->numNodes;i++)
         for(j = 0; j < G->numNodes;j++)
             G->arc[i][j] = INFINITYC;
    
    //4.输入边表信息
    for (k = 0; k < G->numEdges;k++){
        printf("输入边(vi,vj)上的下标i,下标j,权w\n");
        scanf("%d,%d,%d",&i,&j,&w);
        
        G->arc[i][j] = w;
        //如果无向图,矩阵对称;
        G->arc[j][i] = G->arc[i][j];
        
    }
    /*5.打印邻接矩阵*/
    for (int i = 0; i < G->numNodes; i++) {
        printf("\n");
        for (int j = 0; j < G->numNodes; j++) {
            printf("%d ",G->arc[i][j]);
        }
    }
    printf("\n");
}

swift

let MAXVES = 100
let INFINITYC = 0

struct MGraph {
    var vexs:Array<String> = Array<String>()
    var arc:Array<Array<Int>> = Array<Array<Int>>()
    var numNodes:Int = 0, numEdges:Int = 0
    
    static func create() -> MGraph {
        var grap = MGraph()
        //1. 输入顶点数/边数
        print("输入顶点数和边数:")
        if let a = readLine()?.split(separator: ",") {
            grap.numNodes = Int(String(a.first ?? "")) ?? 0
            grap.numEdges = Int(String(a.last ?? "")) ?? 0
        }
        print("顶点数:\(grap.numNodes)和边数:\(grap.numEdges)")
        //2.输入顶点信息/顶点表
        print("输入顶点名称:")
        var i = 0
        while i < grap.numNodes {
            if let a = readLine() {
                grap.vexs.append(a)
            }
            i += 1
        }
        print("顶点表:\(grap.vexs)")
        //3.初始化邻接矩阵
        i = 0
        while i < grap.numNodes {
            var array = Array<Int>()
            var j = 0
            while j < grap.numNodes {
                array.append(INFINITYC)
                j += 1
            }
            grap.arc.append(array)
            i += 1
        }
        i = 0
        while i < grap.numEdges {
            print("输入边(vi,vj)上的下标i,下标j,权w");
            if let a = readLine()?.split(separator: ",") {
                grap.arc[Int(String(a.first ?? "")) ?? 0][Int(String(a[1])) ?? 0] = Int(String(a.last ?? "")) ?? 0
                grap.arc[Int(String(a[1])) ?? 0][Int(String(a.first ?? "")) ?? 0] = Int(String(a.last ?? "")) ?? 0
            }
            i += 1
        }
        
        return grap
    }
}

let grap = MGraph.create()
print(grap)

2、邻接表

#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"


#define M 100
#define true 1
#define false 0

typedef char Element;
typedef int BOOL;
//邻接表的节点
typedef struct Node{
    int adj_vex_index;  //弧头的下标,也就是被指向的下标
    Element data;       //权重值
    struct Node * next; //边指针
}EdgeNode;

//顶点节点表
typedef struct vNode{
    Element data;          //顶点的权值
    EdgeNode * firstedge;  //顶点下一个是谁?
}VertexNode, Adjlist[M];

//总图的一些信息
typedef struct Graph{
    Adjlist adjlist;       //顶点表
    int arc_num;           //边的个数
    int node_num;          //节点个数
    BOOL is_directed;      //是不是有向图
}Graph, *GraphLink;

void creatGraph(GraphLink *g){
    int i,j,k;
    EdgeNode *p;
    
    //1. 顶点,边,是否有向
    printf("输入顶点数目,边数和有向?:\n");
    scanf("%d %d %d", &(*g)->node_num, &(*g)->arc_num, &(*g)->is_directed);
    
    //2.顶点表
     printf("输入顶点信息:\n");
    for (i = 0; i < (*g)->node_num; i++) {
        getchar();
        scanf("%c", &(*g)->adjlist[i].data);
        (*g)->adjlist[i].firstedge = NULL;
    }
    
    //3.
    printf("输入边信息:\n");
    for (k = 0; k < (*g)->arc_num; k++){
        getchar();
        scanf("%d %d", &i, &j);
        
        //①新建一个节点
        p = (EdgeNode *)malloc(sizeof(EdgeNode));
        //②弧头的下标
        p->adj_vex_index = j;
        //③头插法插进去,插的时候要找到弧尾,那就是顶点数组的下标i
        p->next = (*g)->adjlist[i].firstedge;
        //④将顶点数组[i].firstedge 设置为p
        (*g)->adjlist[i].firstedge = p;
        
        //j->i
        if(!(*g)->is_directed)
        {
            // j -----> i
            //①新建一个节点
            p = (EdgeNode *)malloc(sizeof(EdgeNode));
            //②弧头的下标i
            p->adj_vex_index = i;
            //③头插法插进去,插的时候要找到弧尾,那就是顶点数组的下标i
            p->next = (*g)->adjlist[j].firstedge;
            //④将顶点数组[i].firstedge 设置为p
            (*g)->adjlist[j].firstedge = p;
        }
    }
}

void putGraph(GraphLink g){
    int i;
    printf("邻接表中存储信息:\n");
    //遍历一遍顶点坐标,每个再进去走一次
    for (i = 0; i < g->node_num; i++) {
        EdgeNode * p = g->adjlist[i].firstedge;
        while (p) {
            printf("%c->%c ", g->adjlist[i].data, g->adjlist[p->adj_vex_index].data);
            p = p->next;
        }
        printf("\n");
    }
}

swift

//邻接表的节点
class Node {
    var adj_vex_index:Int //弧头的下标,也就是被指向的下标
    var data:Int   //权重值
    var next:Node?
    init(adj_vex_index:Int, data:Int) {
        self.adj_vex_index = adj_vex_index
        self.data = data
    }
}
extension Node:CustomStringConvertible {
    var description: String {
        if next == nil {
            return "adj_vex_index:\(adj_vex_index),data:\(data)"
        }
        return "adj_vex_index:\(adj_vex_index),data:\(data),next->"+String(describing: next)
    }
}
//顶点节点表
class VNode {
    var data:String //顶点的值
    var firstedge:Node?  //顶点下一个是谁?
    init(data:String) {
        self.data = data
    }
}
extension VNode:CustomStringConvertible {
    var description: String {
        return "data:\(data),firstedge:"+String(describing: firstedge)
    }
}
//图的一些信息
class Graph {
    var adjlist = Array<VNode>() //顶点表
    var arc_num = 0   //边的个数
    var node_num = 0   //节点个数
    var is_directed = false  //是不是有向图
    
    static func create() -> Graph {
        let grap = Graph()
        //1. 顶点,边,是否有向
        print("输入顶点数目,边数和有向?:");
        if let a = readLine()?.split(separator: ",") {
            grap.node_num = Int(String(a.first ?? "")) ?? 0
            grap.arc_num = Int(String(a[1])) ?? 0
            grap.is_directed = Bool(String(a.last ?? "")) ?? false
        }
        //2.顶点表
        print("输入顶点信息:");
        for _ in 0..<grap.node_num {
            if let a = readLine(){
                let node = VNode(data: a)
                grap.adjlist.append(node)
            }
        }
        //3.
        print("输入边信息:");
        for _ in 0..<grap.arc_num {
            if let a = readLine()?.split(separator: ",") {
                //①新建一个节点②弧头的下标③头插法插进去,插的时候要找到弧尾,那就是顶点数组的下标i④将顶点数组[i].firstedge 设置为node
                let node = Node(adj_vex_index: Int(String(a.last ?? "")) ?? 0, data: 1)
                node.next = grap.adjlist[Int(String(a.first ?? "")) ?? 0].firstedge
                grap.adjlist[Int(String(a.first ?? "")) ?? 0].firstedge = node
                if !grap.is_directed {
                    let node = Node(adj_vex_index: Int(String(a.first ?? "")) ?? 0, data: 1)
                    node.next = grap.adjlist[Int(String(a.last ?? "")) ?? 0].firstedge
                    grap.adjlist[Int(String(a.last ?? "")) ?? 0].firstedge = node
                }
            }
        }
        return grap
    }
}

extension Graph : CustomStringConvertible {
    var description: String {
        return "arc_num:\(arc_num),node_num:\(node_num),is_directed:\(is_directed),adjlist:"+String(describing: adjlist)
    }
}

let grap = Graph.create()
print(grap)