数组模拟实现的单链表 → 邻接表

75 篇文章 3 订阅
17 篇文章 1 订阅

【知识点】
在算法竞赛中,对算法的时间复杂度要求都比较高。
而利用结构体struct实现的单链表比用数组模拟实现的单链表运行速度慢,因此算法竞赛选手多用数组模拟实现单链表。
现对单链表的数组模拟实现简述如下:
一、变量含义

head:头指针。初始化时指向空结点(值为-1),插入元素后指向头结点后的第一个元素。
idx:存储结点编号 
e[idx]:存储结点idx的值
ne[idx]:存储结点idx的next指针 

二、主要操作
1.单链表的初始化

void init() { //单链表初始化
	head=-1;
	idx=0;
}


2.利用头插法在链表头插入元素 a 

void insert(int a) { //利用头插法在链表头插入元素a
	e[idx]=a,ne[idx]=head,head=idx++;
}



3.在第k个插入的元素后插入一个元素a 

void add(int k, int a) { //在第k个插入的元素后插入一个元素a
	e[idx]=a;
	ne[idx]=ne[k];
	ne[k]=idx++;
}


4.删除第k个插入的元素后面的元素

void remove(int k) { //删除第k个插入的元素后面的元素
	ne[k]=ne[ne[k]];
}


 

三、单链表 → 邻接表
邻接表本质上是以图/树中各个结点为头结点构成的多个单链表,因此必然可以上文所述进行理解。只是稍作拓展而已。
图/树的数组模拟实现的邻接表代码为:

void add(int a,int b) { //Adjacent List, Head insertion method.
	e[idx]=b,ne[idx]=h[a],h[a]=idx++; //Insert node b.
}

在此实现方式下,对树进行遍历的代码模板为:

void dfs(int u) { //Recursion, u is a node
	......
	for(int i=h[u]; i!=-1; i=ne[i]) { //Traverse the tree
		int j=e[i];
		dfs(j);
		......
	}
}

由于树是特殊的图,所以数组模拟实现的邻接表表示方法完全适用于图及树。
由于
树的遍历需从树根开始,所以在对树进行遍历时需要编码判断哪个结点是树根。而图可以从任意一个结点开始进行遍历

若要以文献 http://wiki.jikexueyuan.com/project/easy-learn-algorithm/clever-adjacency-list.html 来理解上文所述的图/树的数组模拟实现的邻接表代码,需约定如下:
按照读入的顺序为每一条边进行编号(从1开始计数);
idx表示树中结点的编号;
h[] 相当于文献 
http://wiki.jikexueyuan.com/project/easy-learn-algorithm/clever-adjacency-list.html 中的 first[] 数组,初始化为-1;
ne[] 相当于文献 
http://wiki.jikexueyuan.com/project/easy-learn-algorithm/clever-adjacency-list.html 中的 next[] 数组。

若按序插入边(1,4)、(4,3)、(1,2)、(2,4)、(1,3),按照上文所述的图/树的数组模拟实现的邻接表代码,其模拟执行过程如下图所示:


 

显然,由上图可以查看所有以1 号结点为起点的每一条边的遍历过程。
首先由 h[1] 提供的值开始,然后再依据 ne[] 数组提供的值便可查看整个过程。
当然,下图可以更直观的方式展示。




 



【参考文献】
http://wiki.jikexueyuan.com/project/easy-learn-algorithm/clever-adjacency-list.html https://blog.csdn.net/Ahub_Ha/article/details/108401760 
https://blog.csdn.net/riba2534/article/details/54571026
https://www.acwing.com/solution/content/3472/
https://www.acwing.com/solution/content/16251/

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值