用数组模拟——单链表,树和图的存储(邻接表、邻接矩阵)

一. 单链表

int head, idx; //head存储链表头,idx表示当前模拟到了哪个结点
int e[N], ne[N]; //e[]存储数据域的值,ne[]存储结点的next指针

初始化

为空链表,所以:

void init()
{
    head = -1;
    idx = 0;
}

存储元素

在表头插入一个数x

在这里插入图片描述

void add_to_head(int x)
{
    e[idx] = x;
    ne[idx] = head;
    head = idx ++;
}

删除头结点

在这里插入图片描述

删除前,head = 0;ne[0] = 1;
若想删除头结点a1,只需让head指针直接指向a2的下标1即可,即head = ne[head]

void remove()
{
    head = ne[head];
}

插入

在下标为k的点后面插入一个点x
在这里插入图片描述
例:将a6插入到a2后面。

  1. 首先将a6的值存起来
  2. 将a6的next域指向a3
  3. 将a2的next域指向a6
void add(int k, int x)
{
    e[idx] = x;
    ne[idx] = ne[k]; //ne[5] = ne[1] = 2;
    ne[k] = idx ++; //ne[1] = 5;
}

删除

删除下标为k的点后面的点
在这里插入图片描述
例: 若删除a3,就直接让a2的next域指向a4,跳过a3。即ne[1] = ne[ne[1]] = 3;

void delete(int k)
{
    ne[k] = ne[ne[k]];
}

二. 树和图的存储

  1. 树是一种特殊的图,所以树的存储可以当成图的存储来做。
  2. 图的存储可以分为邻接表和邻接矩阵两种方式。

Ⅰ. 邻接表

在这里插入图片描述
对于上图的邻接表,把每一行看成是一个单链表,其中每一个单链表存储的是一个点可以到的其它点的集合。

// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点,e[]存储数据域的值,ne[]存储结点的next指针
int h[N], e[N], ne[N]; 
int idx; //idx表示当前的起点模拟到了哪个结点

初始化

只有n个点,没有边,所以初始化时:

idx = 0;
memeset(h, -1, sizeof(h));

将边加入图或树中

对于每一个单链表,插入一条从a到b的边:
可以把每一行看成是一个单链表,每一个单链表的头结点就是h[a]。当发现有从a到b的边时,就变相的是向头结点为a的单链表的头那儿中插入一个点b,所以就把单链表的存储那儿的代码的head换成h[a]就好了。

//添加一条边:a -> b
void add(int a, int b)
{
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx ++;
}

Ⅱ. 邻接矩阵

在这里插入图片描述

如上图的有向带权图,直接可以用二维数组来模拟存储过程:

int g[N][N]; //g[i][j]: 从点i到点j的距离
int n, m;  //n个点,m条边
int a, b, c; //点a,b, 权重为c

int main()
{
    
    cin >> n >> m;
    
    //初始化数组
    memset(g, 0x3f3f3f3f, sizeof(g));
    
    for(int i = 1; i <= m; i++)
    {
        cin >> a >> b >> c;
        
        g[a][b] = c;
    }
}

对于无向图中的边ab,存储时存储两条有向边a->b, b->a

g[a][b] = g[b][a] = c;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值