单链表、树、图的存储(数组存储)

14 篇文章 0 订阅
2 篇文章 0 订阅

一、单链表

1. 存储方式(不总结结构体存储)

单链表的存储,主要是以下几个方面:

  • 存储每个点的值e[i]
  • 存储每个结点的下一个结点ne[i]
  • 存储头结点head

用这3个变量去模拟链表。其中每个结点用数组下标去索引,即每个点对应一个下标。相应的,ne指针就指向下一个结点的下标,而非地址。
在这里插入图片描述

/**
* head : 指向 头结点的下标
* e[i] : 下标为i的点的值
* ne[i] : 下标为i的点 的 下一个结点的下标
* idx : 结点个数。[0, idx)的每个数对应一个结点
*/
int head, e[N], ne[N], idx;

2. 操作

(1)初始化init()

链表初始化,即链表为空。头结点指针head指向-1,结点个数idx = 0。

void init()
{
	head = -1;
	idx = 0;
}
(2)插入结点:插入表头

在这里插入图片描述
可以看到,操作主要分两步:

  1. 新结点的ne指向当前头结点
  2. head指向新结点
/**
* x : 插入的结点值
*/
void add_to_head(int x)
{
	e[idx] = x; // 1. 存储节点的值
	ne[idx] = head; // 2. 新结点ne指向当前头结点
	head = idx; // 3. head指向新结点
	idx ++ ; // 4. 节点个数+1
	
    /* idx实际上记录了每个点是第几个输入的点 */
}
(3)插入结点:在输入的第k个点后面插入

前面说到,idx记录了每个点是第几个输入的。所以对于5来说,idx=1在这里插入图片描述

void add(int k, int x)
{
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] = idx ++ ;
}
(4)删除第k个输入的结点

在这里插入图片描述

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

二、树、图的存储

由于树是特殊的图,所以只讨论图的存储。

对于图来说,有两种存储方式:

  • 邻接矩阵
  • 邻接表

下面主要说明邻接表的存储方式。邻接表是指:对于图上的每个结点来说,用一个单链表存储它的邻接点,如下图所示:

在这里插入图片描述

所以,与单链表的存储方式相比,不同点在于:有很多头结点,所以head是一个数组。对于无权图来说,代码如下:

/**
* h[i] : 指向头结点i
* e[i] : 第i个点的值
* ne[i] : 第i个点的下一个结点
* idx : 节点个数
*
*  N : 结点个数
*  M : 2 * N, 因为无向图会插入两次
*/
int h[N], e[M], ne[M], idx;

void init() // 初始化邻接表
{
	
	memset(h, -1, sizeof(h));
	idx = 0;
}

void add(int a, int b) // 在a的后面插入b
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ; 
}	

int main()
{
	...
	// 遍历图
	// u为根结点
	for(int i = h[u]; i != -1; i = ne[i])
	{
		...
	}
}

对于有权图来说,代码如下:

/**
* h[i] : 指向头结点i
* e[i] : 第i个点的值
* ne[i] : 第i个点的下一个结点
* idx : 节点个数。同时也指明了插入的第几个点,插入的第几条边
*
*  N : 结点个数
*  M : 2 * N, 因为无向图会插入两次
*/
int h[N], w[M], e[M], ne[M], idx; /* 加了一个w[M], 表示每条边的权重 */

void init() // 初始化邻接表
{
	memset(h, -1, sizeof(h));
	idx = 0;
}

void add(int a, int b, int c) // 在a的后面插入b, 边权为c
{
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ; 
}	

int main()
{
	...
	// 遍历图
	// u为根结点
	for(int i = h[u]; i != -1; i = ne[i])
	{
		...
	}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值