数据结构C语言实现——图及最短路径实现

本文记录了自己学习数据结构与算法课程的图结构实现及最短路径算法实现

map.h

#ifndef _MAP_H_
#define _MAP_H_
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

#define MAX_VERTEX_NUM 100
#define MAX_DIS INT_MAX

typedef char VertexType;
typedef int EdgeType;
//循环队列//
typedef struct Queue{
VertexType data[MAX_VERTEX_NUM];
int head;
int tail;
}CQueue;
//栈//
typedef struct Stack{
VertexType data[MAX_VERTEX_NUM];
int top;
}Stack;

//图的顺序存储----邻接矩阵//
typedef struct Map{
    VertexType Vertex[MAX_VERTEX_NUM]; //顶点集
    EdgeType Edge[MAX_VERTEX_NUM][MAX_VERTEX_NUM];  //边集
    int vertexnum; //定点数
    int edgenum;   //边数
}UD_Map;//undirection

//图的链式存储---邻接表
typedef struct ArcNode{
int Adjvex;//顶点序号
int Weight;//权值
struct ArcNode* nextarc;//指向下一条弧的指针
}ArcNode;//弧结点

typedef struct VerNode{
VertexType vertex;//顶点数据
ArcNode *firstarc;//指向第一条弧的指针
}VerNode;//表头结点

typedef struct list{
VerNode Vertex[MAX_VERTEX_NUM];//表头结点数组
int vexnum,arcnum;
}Adj_List;

//关键活动
typedef struct Activity
{
    VertexType s,t;
}Activity;
typedef struct Key_Act
{
    Activity buf[MAX_VERTEX_NUM];
}Key_Act;

//链表//
typedef struct Node{
int Verdata;
struct Node *next;
}ListNode,* LinkList;

LinkList Path[MAX_VERTEX_NUM];
int Dist[MAX_VERTEX_NUM];


int Visited[MAX_VERTEX_NUM];//全局访问
//深度优先遍历//
int Creat_Map(UD_Map *m); //创建图
void TraverseMap(UD_Map *m); //遍历图
void DepthFirstSearch(UD_Map *m,int i); //深度优先遍历

//广度优先遍历//
void Creat_UDMap(UD_Map *m);
void BreadthFirstSearch(UD_Map *m,int v0);
int FirstAdj(UD_Map *m,int v);
int NextAdj(UD_Map *m,int v,int pre_v);
void Init_CQueue(CQueue *q);

int EnCQueue(CQueue *q,VertexType e);
int OutCQueue(CQueue *q,VertexType *e);
int GetCQueue(CQueue *q,VertexType *e);
int Is_empty(CQueue *q);

//关键路径//
int start,ending;//全局变量起点和终点
//栈声明函数//
void Init_Stack(Stack *s);
bool Push(Stack *s,VertexType e);
bool Pop(Stack *s,VertexType *e);
bool Get(Stack *s,VertexType *e);
bool Is_Empty(Stack *s);
void Print_Stack(Stack *s,Key_Act *Key);
void Empty_Stack(Stack *s);
//邻接表声明函数//
void Init_KeyAct(Key_Act *Key);
void Ini_Adj_List(Adj_List *L);
void Creat_Adj_List(Adj_List *L);
void FindInD(Adj_List L,int degree[]);
bool TopoSort(Adj_List L,Stack *T,VertexType ve[]);
int Get_CriticalKey(Adj_List L,Key_Act *Key);
void Print_CriticalPath(Key_Act *Key);

//最短路径//
//map
void Init_DMap(UD_Map *M);
void Creat_DMap(UD_Map *M,int *v0);
void Find_MinPath(UD_Map *M,int v0);
void print_minpath(LinkList L);
void Print_MinPaths(UD_Map *M,VertexType v0);
void Print_Dist(int dist[],int v0,int vex_num);
//linklist
void Init_List(LinkList *L);
void AddTail(LinkList *L,VertexType ver);
bool Member(VertexType ver,LinkList s);
void CopyPath(LinkList *T,LinkList *S);
void Clear_Link(LinkList *L);
#endif // _MAP_H

map.c

#include"map.h"

//*********↓****图的深度优先遍历***************//
int Creat_Map(UD_Map *m)//创建图
{
    int i,j;
    scanf("%d",&(m->vertexnum));
    m->edgenum = 2*m->vertexnum - 1;
    for(i=0;i<m->vertexnum;i++)//初始化边集
    {
        for(j=0;j<m->vertexnum;j++)
        {
            scanf("%d",& (m->Edge[i][j]));
        }
    }
    return 1;
}

void TraverseMap(UD_Map *m)//遍历图
{
    int i,count = 0;
    for(i=0;i<m->vertexnum;i++)
    {
        Visited[i] = 0;
    }
    for(i=0;i<m->vertexnum;i++)
    {
        if(Visited[i] == 0)
        {
            DepthFirstSearch(m,i);
            count ++;
        }
    }
    printf("%d",count);
}

void DepthFirstSearch(UD_Map *m,int i)//深度优先遍历
{
    int j;
    Visited[i] = 1;
    for(j=0;j<m->vertexnum;j++)
    {
        if(Visited[j] == 0 && m->Edge[i][j] == 1)
        {
            DepthFirstSearch(m,j);
        }
    }
}
//*********↑****图的深度优先遍历***************//


//*********↓****图的广度优先遍历***************//

void Init_CQueue(CQueue *q)
{
    q->head = q->tail = 0;
}
int EnCQueue(CQueue *q,VertexType e)//入队--队尾入
{
    if((q->tail+1) % MAX_VERTEX_NUM == q->head)
    {
        printf("full!\n");
        return -1;
    }
    q->data[q->tail] = e;
    q->tail= (q->tail+1) % MAX_VERTEX_NUM;
    return 1;
}

int OutCQueue(CQueue *q,VertexType *e)
{
    if(q->head == q->tail)
    {
        printf("empty!\n");
        return -1;
    }
    *e = q->data[q->head];
    q->head = (q->head + 1) % MAX_VERTEX_NUM;
    return 1;
}

int GetCQueue(CQueue *q,VertexType *e)
{
    if(q->head == q->tail)
    {
        printf("empty!\n");
        return -1;
    }
    *e = q->data[q->head];
    return 1;
}

int Is_empty(CQueue *q)
{
    return (q->head == q->tail);
}

void Creat_UDMap(UD_Map *m)//创建一个图
{
    int i,j;
    scanf("%d",&(m->vertexnum));
    for(i=0;i<m->vertexnum;i++)
    {
        scanf("%d",&(m->Vertex[i]));
    }
    for(i=0;i<m->vertexnum;i++)
    {
        for(j=0;j<m->vertexnum;j++)
        {
            scanf("%d",&(m->Edge[i][j]));
        }
    }
    for(i=0;i<m->vertexnum;i++)//访问数组初始化
    {
        Visited[i] = 0;
    }
}

void BreadthFirstSearch(UD_Map *m,int v0)
{
    CQueue q;
    int Adj_index,v;
    printf("%d ",m->Vertex[v0]);
    Visited[v0] = 1;
    Init_CQueue(&q);
    EnCQueue(&q,v0);
    while(!Is_empty(&q))
    {
        OutCQueue(&q,&v);
        Adj_index = FirstAdj(m,v);
        while(Adj_index != -1)//找到了
        {
            if(Visited[Adj_index] == 0)
            {
                printf("%d ",m->Vertex[Adj_index]);
                Visited[Adj_index] = 1;
                EnCQueue(&q,Adj_index);
            }
            Adj_index = NextAdj(m,v,Adj_index);
        }
    }
}

int FirstAdj(UD_Map *m,int v)
{
    int i,w = -1;
    for(i=0;i<m->vertexnum;i++)
    {
        if(m->Edge[v][i] == 1)
        {
            return i;
        }
    }
    return w;
}

int NextAdj(UD_Map *m,int v,int pre_v)
{
    int i;
    for(i = pre_v+1;i<m->vertexnum;i++)
    {
        if(m->Edge[v][i] == 1)
        {
            return i;
        }
    }
    return -1;
}
//**********↑***图的广度优先遍历***************//


//**************↓***关键路径*******************//
//栈定义函数//
void Init_Stack(Stack *s)
{
    s->top = -1;
}
void Print_Stack(Stack *s,Key_Act *Key)
{
    int i;
    for(i=0;i<=s->top;i++)
    {
        printf("%d %d\n",Key->buf[s->data[i]].s,Key->buf[s->data[i]].t);
    }

}
void Empty_Stack(Stack *s)
{
    s->top = -1;
}
bool Push(Stack *s,VertexType e)
{
    if(s->top == MAX_VERTEX_NUM-1)
    {
        return false;
    }
    s->top++;
    s->data[s->top] = e;
    return true;
}
bool Pop(Stack *s,VertexType *e)
{
    if(s->top == -1)
    {
        return false;
    }
    *e = s->data[s->top];
    s->top--;
    return true;
}
bool Get(Stack *s,VertexType *e)
{
    if(s->top == -1)
    {
        return false;
    }
    *e = s->data[s->top];
    return true;
}
bool Is_Empty(Stack *s)
{
    return s->top == -1;
}
//邻接表定义函数//
void Ini_Adj_List(Adj_List *L)
{
    int i;
    for(i=0;i<L->vexnum;i++)
    {
        L->Vertex[i].vertex = i;
        L->Vertex[i].firstarc = NULL;
    }
}

void Creat_Adj_List(Adj_List * L)
{
    int i,ver_S,ver_T,weight;
    ArcNode * temp,*Add;
    scanf("%d %d",&L->vexnum,&L->arcnum);
    Ini_Adj_List(L);
    for(i=0; i<L->arcnum; i++)
    {
        scanf("%d %d %d",&ver_S,&ver_T,&weight);
        temp = L->Vertex[ver_S].firstarc;//temp指向第一个边结点
        if(temp == NULL)
        {
            Add = (ArcNode *)malloc(sizeof(ArcNode));
            Add->nextarc = NULL;
            L->Vertex[ver_S].firstarc = Add;
            Add->Adjvex = ver_T;
            Add->Weight = weight;
        }else
        {
            while(temp->nextarc != NULL)
            {
                temp = temp->nextarc;
            }
            Add = (ArcNode*)malloc(sizeof(ArcNode));
            Add->nextarc = temp->nextarc;
            temp->nextarc = Add;
            Add->Adjvex = ver_T;
            Add->Weight = weight;
        }
    }
}

void FindInD(Adj_List L,int degree[])
{
    ArcNode *p;
    int i;
    for(i=0;i<L.vexnum;i++)
    {
        degree[i] = 0;
    }
    for(i=0;i<L.vexnum;i++)
    {
        p = L.Vertex[i].firstarc;
        if(p == NULL)
            ending = i;
        while(p!=NULL)
        {
            degree[p->Adjvex]++;
            p = p->nextarc;
        }
    }
    for(i=0;i<L.vexnum;i++)
    {
        if(degree[i] == 0)
            start = i;
    }
    //printf("start:%d ending:%d \n",start,ending);
}

bool TopoSort(Adj_List L,Stack *M,VertexType ve[])
{
    Stack T;
    Init_Stack(&T);
    int indegree[MAX_VERTEX_NUM];
    int i,j,count=0,k;
    ArcNode *p;
    FindInD(L,indegree);//计算入度
    for(i=0;i<L.vexnum;i++)
    {
        if(indegree[i] == 0);
        Push(&T,i);
    }
    while(!Is_Empty(&T))
    {
        Pop(&T,&i);
        //printf("%d ",L.Vertex[i].vertex);
        Push(M,i);
        count ++;
        p = L.Vertex[i].firstarc;
        while(p!=NULL)
        {
            k = p->Adjvex;
            indegree[k]--;
            if(indegree[k] == 0)
            {
                Push(&T,k);
            }
            p = p->nextarc;
        }
    }
    if(count < L.vexnum)
    {
        return false;
    }else//求取ve[]
    {
        for(i=0;i<L.vexnum;i++)
            ve[i] = 0;//初始化
        for(i=1;i<L.vexnum;i++)//当前求取的ve[i]
        {
            for(j=0;j<L.vexnum;j++)
            {
                p = L.Vertex[j].firstarc;
                while(p!=NULL)
                {
                    if(p->Adjvex == i)
                    {
                        if(ve[j]+p->Weight > ve[i])
                        {
                            ve[i] = ve[j]+p->Weight;
                        }
                    }
                    p=p->nextarc;
                }
            }
        }
        return true;
    }
}

int Get_CriticalKey(Adj_List L,Key_Act *Key)
{

    int i,j,w,ae,al,count=0;
    //char tag;
    ArcNode *temp;
    int ve[MAX_VERTEX_NUM],vl[MAX_VERTEX_NUM];
    Stack T;
    Init_Stack(&T);//存储拓扑顺序
    if(!TopoSort(L,&T,ve))
        return false;
    for(i=0;i<L.vexnum;i++)
        vl[i] = ve[i];
    while(!Is_Empty(&T))
    {
        Pop(&T,&j);
        temp = L.Vertex[j].firstarc;
        while(temp!=NULL)
        {
            i = temp->Adjvex;
            w = temp->Weight;
            if(vl[j] > vl[i]-w)
                vl[j] = vl[i]-w;
            temp = temp->nextarc;
        }
    }
    for(j=0;j<L.vexnum;j++)
    {
        temp = L.Vertex[j].firstarc;
        while(temp != NULL)
        {
            i = temp->Adjvex;
            w = temp->Weight;
            ae = ve[j];
            al = vl[i] - w;
            //tag =(ae == al)?'*':' ';
            //printf("%d %d %c \n",j,i,tag);
            if(ae == al)
            {
                Key->buf[count].s = j;
                Key->buf[count].t = i;
                count ++;
            }
            temp = temp->nextarc;
        }
    }
    /*
    for(i=0;i<count;i++)
    {
        printf("(%d-->%d)", Key->buf[i].s, Key->buf[i].t);
    }
    printf("\n");
    */
    return true;
}

void Init_KeyAct(Key_Act *Key)
{
    int i;
    for(i=0;i<MAX_VERTEX_NUM;i++)
    {
        Key->buf[i].s = -1;
        Key->buf[i].t = -1;
    }
}
void Print_CriticalPath(Key_Act *Key)
{
    Stack find;
    int i,j,temp=0;
    Init_Stack(&find);
    for(i=0;Key->buf[i].s == start;i++)
    {
        Push(&find,i);
        for(j=i+1;(j<MAX_VERTEX_NUM && Key->buf[j].t != -1);j++)
        {
            Get(&find,&temp);
            if(Key->buf[j].s == Key->buf[temp].t)
            {
               Push(&find,j);
            }
        }
        Get(&find,&temp);
        if(Key->buf[temp].t == ending)
        {
            Print_Stack(&find,Key);
        }else
        {
            Empty_Stack(&find);
        }
    }
}
//**************↑***关键路径*******************//

//**************↓***最短路径*******************//
void Init_DMap(UD_Map *M)//邻接矩阵初始化
{
    int i,j;
    for(i=0;i<M->vertexnum;i++)
    {
        M->Vertex[i] = i;
    }
    for(i=0;i<M->vertexnum;i++)
    {
        for(j=0;j<M->vertexnum;j++)
        {
            M->Edge[i][j] = MAX_DIS;
        }
    }
}

void Creat_DMap(UD_Map *M,int *v0)//初始化图
{
    int i,j,Weight,s;
    scanf("%d",&(M->vertexnum));//输入节点数
    scanf("%d",&s); //输入源节点
    *v0 = s;
    Init_DMap(M);//初始化邻接矩阵
    for(i=0;i<M->vertexnum;i++)
    {
        for(j=0;j<M->vertexnum;j++)
        {
            scanf("%d",&Weight);//输入有向边始终和权重
            if(Weight != 0)
            {
                M->Edge[i][j] = Weight;
            }
        }
    }
}

void Find_MinPath(UD_Map *M,int v0)
{
    int i,k,t,min;
    LinkList s;//初始化S集:最小路径集
    for(i=0;i<M->vertexnum;i++)
    {
        Init_List(&Path[i]);//初始化最初路径
        Dist[i] = M->Edge[v0][i];
        if(Dist[i] < MAX_DIS)//如果有路径,加入
        {
            AddTail(&Path[i],M->Vertex[v0]);
            AddTail(&Path[i],M->Vertex[i]);
        }
    }
    Init_List(&s);//初始化S集
    AddTail(&s,M->Vertex[v0]);//将起始点加入S集
    for(t=1;t<M->vertexnum;t++)//循环M->vertexnum-1次
    {
        min = MAX_DIS;
        for(i=0;i<M->vertexnum;i++)//寻找最小路径长//
        {
            if(!Member(M->Vertex[i],s) && Dist[i]< min)//节点i不在S集并且起始点到i的路径长度小于U-S集中最小值
            {
                k = i;
                min = Dist[i];
            }
        }
        AddTail(&s,M->Vertex[k]);//将该结点加入S集
        for(i=0;i<M->vertexnum;i++)//更新从源点利用S集元素到达其余点的长度和路径
        {
            //目标点不在S集并且源点利用K点到目标点的距离小于直接之前距离
            if(!Member(M->Vertex[i],s) && (Dist[k] + M->Edge[k][i] < Dist[i]) && Dist[k] + M->Edge[k][i]>0)
            {
                Dist[i] = Dist[k] + M->Edge[k][i];
                CopyPath(&Path[i],&Path[k]);//复制路径
                AddTail(&Path[i],M->Vertex[i]);
            }
        }
    }
}
void Print_Dist(int dist[],int v0,int vex_num)//itc用
{
    int i;
    for(i=0;i<vex_num;i++)
    {
        if(i != v0)
        {
            if(Dist[i] == MAX_DIS)
            {
                printf("%d ",-1);
            }else
            {
                printf("%d ",Dist[i]);
            }

        }
    }
}
void print_minpath(LinkList L)
{
    ListNode *temp;
    temp = L->next;
    while(temp!=NULL)
    {
        printf("%d ",temp->Verdata);
        temp = temp->next;
    }
    printf("\n");
}

void Print_MinPaths(UD_Map *M,VertexType v0)
{
    int i;
    for(i=0;i<M->vertexnum;i++)
    {
        if(i != v0)
        {
            print_minpath(Path[i]);
        }
    }
}

void Init_List(LinkList *L)
{
    (*L) = (LinkList)malloc(sizeof(ListNode));//创建头节点
    (*L)->next = NULL;
}

void AddTail(LinkList *L,VertexType ver)
{
    ListNode * temp, *tail;
    tail = (*L);
    while(tail->next != NULL)//找到尾节点
    {
        tail = tail->next;
    }
    temp =(LinkList)malloc(sizeof(ListNode));//申请一个节点
    if(temp)
    {
        temp->Verdata = ver;
        temp->next = NULL;//---> temp->next = NULL;
        tail->next = temp;
    }
}

bool Member(VertexType ver,LinkList s)
{
    ListNode *temp;
    temp = s->next;
    while(temp != NULL)
    {
        if(temp->Verdata == ver)
            return true;
        temp = temp->next;
    }
    return false;

}

void CopyPath(LinkList *T,LinkList *S)// T = S;
{
    ListNode *temp_s,*temp_t,*add;
    temp_t = (*T);
    temp_s = (*S)->next;
    Clear_Link(T);
    while(temp_s!=NULL)
    {
        add = (LinkList)malloc(sizeof(ListNode));
        if(add)
        {
            add->Verdata = temp_s->Verdata;
            add->next = temp_t->next;
            temp_t->next = add;
            temp_s = temp_s->next;
            temp_t = temp_t->next;
        }

    }
}

void Clear_Link(LinkList *L)
{
    ListNode *temp,*del;
    temp = (*L);
    while(temp->next != NULL)
    {
        del = temp->next;
        temp->next = del->next;
        free(del);
    }
}
//**************↑***最短路径*******************//
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值