邻接表-动态和静态的学习

上一篇用到了邻接表,这里学习一下数据结构。

 

我们知道图的保存方式有很多种,邻接矩阵adjMax【】【】,邻接表。。。。

邻接矩阵适合稠密图,而邻接表在表示稀疏图时很节省内存。

 

而邻接表又有动态和静态之分,静态和动态就不多做解释了,动态就是有多少用多少,静态你要提前分配好够用的内存,一般会比实际用的大一些。。。。

 

下面是静态表的一个实例

#include <iostream>
#include <queue>
using namespace std;
const long edge_maxn = 1005;  //边的最大上限
const long point_maxn = 105;  //点的最大上限
struct node
{/*node存储边,一个edge代表一条边*/
	int v;  //终点位置
	int w;  //权值
	int next;  //同一起点的下一条边存储在edge数组中的位置(理解了这个静态邻接表就可以了)
}edge[edge_maxn];
int pre[point_maxn];  //以该点为起点的第一条边存储在edge数组中的位置
int n; //点的数量
int m; //边的数量
void Init()
{
	memset(pre,-1,sizeof(pre));
	int Index = 1;
	int i,x,y,w;
	for(i=0;i<m;i++)
	{
		scanf("%d%d%d",&x,&y,&w);
		
		edge[Index].v = y;
		edge[Index].w = w;
		edge[Index].next = pre[x];  //保存x起点的上一条边在edge数组中的位置
		pre[x] = Index++;  //位置更新
	}
}
void print()
{
	for(int i=1;i<=n;i++)
	{
		printf("%d/n",i);
		for(int j=pre[i];j!=-1;j=edge[j].next)
		{
			printf(" -> %d value is %d/n",edge[j].v,edge[j].w);
		}
		//printf("/n");
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0))
	{
		Init();
		print();
	}
	return 0;
}


下面是动态表的实例,以poj1511为例

#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
#define MAX_NUM 1000000001
#define MAX_DOTNUM 1000001

int n,m;
queue<int>myqueue;
bool mark[MAX_DOTNUM];
__int64 dis[MAX_DOTNUM];


struct node
{

    int v;
    int w;
    node *next;
}edge[MAX_DOTNUM];//此邻接表用于存储正向图

node reversed_edge[MAX_DOTNUM];//此逆邻接表用于存储逆向图

void initial(node edge[])//邻接表的初始化,里面封装了回收上一次操作所分配之内存的操作
{
    int i;
    node *p;
    node *q;
    for(i=1;i<=n;i++)
    {
        p=&edge[i];
        q=p->next;
        while(q!=NULL)
        {
            p->next=q->next;
            delete q;
            q=p->next;
        }
    }
}


void input_case()//每一个case的输入函数
{

    int i;
    for(i=1;i<=m;i++)
    {
        node *p;
        node *q;
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        /**/
        p=&edge[a];
        q=new node;
        q->v=b;
        q->w=c;
        q->next=p->next;
        p->next=q;
        /**/
        p=&reversed_edge[b];
        q=new node;
        q->v=a;
        q->w=c;
        q->next=p->next;
        p->next=q;
    }
}


void spfa(node edge[])//SPFA部分
{

    int i;
    /**
    memset(mark,false,sizeof(mark));
    for(i=1;i<=n;i++)
        dis[i]=MAX_NUM;
    while(myqueue.size()!=0)
        myqueue.pop();
    /**
    dis[1]=0;
    mark[1]=true;
    myqueue.push(1);
    while(myqueue.size()!=0)//如果队列不空,则进行松弛操作,直到队列空为止
    {
        int temp=myqueue.front();
        myqueue.pop();
        mark[temp]=false;
        node *p;
        for(p=edge[temp].next;p!=NULL;p=p->next)
        {
            if(dis[p->v]>dis[temp]+p->w)
            {
                dis[p->v]=dis[temp]+p->w;
                if(mark[p->v]!=true)
                {
                    myqueue.push(p->v);
                    mark[p->v]=true;
                }
            }
        }
    }
}


int main()
{

    int testcase;
    int i,j;
    __int64 sum;
    scanf("%d",&testcase);
    for(i=1;i<=MAX_DOTNUM-1;i++)
    {
        edge[i].v=i;
        edge[i].w=0;
        edge[i].next=NULL;
    }
    for(i=1;i<=MAX_DOTNUM-1;i++)
    {
        reversed_edge[i].v=i;
        reversed_edge[i].w=0;
        reversed_edge[i].next=NULL;
    }
    for(i=1;i<=testcase;i++)
    {
        sum=0;
        scanf("%d%d",&n,&m);
        initial(edge);
        initial(reversed_edge);
        input_case();
        spfa(edge);
        for(j=1;j<=n;j++)
            sum+=dis[j];
        spfa(reversed_edge);
        for(j=1;j<=n;j++)
            sum+=dis[j];
        printf("%I64d\n",sum);
    }
    system("pause");
    return 0;

}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值