用数组模拟单链表和双链表

单链表和双链表的区别:

单链表的每一个节点只有指向后面的一个指针

双链表每一个节点有两个指针,一个指向前,一个指向后

一.单链表

单链表:可以用来实现邻接表,邻接表可用来存储树和图(最短路问题,最小生成树问题)

1.单链表概念

单链表的缺点:只向后看,不向前看

即可以以O(1)的时间得到下一个节点的地址,向后插入数据,但是如果想知道前一个节点的地址,只能从头遍历

每一个节点都有两个数组:一个是记录当前节点值的数组e[N],一个是记录下一个节点位置的next[N]

用数组来实现单链表

2.单链表的两个基本操作

   1.插入:

   ->向头节点(head)插入x

   ->将x插到下标是k的点后面 

   2.删除:

   ->将下标是k的点后面的点删掉

3.单链表基本操作的代码实现

#include<iostream>

using namespace std;

const int N = 10010;

//head 表示头结点的下标 
//e[i] 表示节点i的值
//ne[i] 指向节点i的next指针是多少(下一个节点的索引)
//idx 存储当前已经用到了哪一个点 

int head,e[N],ne[N],idx; 

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

//将x插到头结点 
void add_to_head(int x){
	e[idx] = x;
	ne[idx] = head;
	head = idx;
	idx++;
} 

//将x插到下标是k的点后面 
void add(int k,int x){
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] = idx ;
	idx++;
} 

//将下标是k的点后面的点删掉 
void delect(int k){
	ne[k] = ne[ne[k]];
} 

int main(){
	
}

4.实现一个完整单链表代码实现

例题:acwing826 单链表

代码实现: 

#include<iostream>

using namespace std;

const int N = 10010;

int head,e[N],ne[N],idx; 

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

void add_to_head(int x){//头结点插入
	e[idx] = x ,ne[idx] = head, head = idx++;
} 

void add(int k,int x){//插入
	e[idx] = x, ne[idx] = ne[k], ne[k] = idx++;
} 

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

int main(){
	int m;
	cin>>m;
	
	init();
	
	while (m--){
		char op;
        cin >> op;
		int k,x;
		if(op == 'H'){
			cin >> x;
			add_to_head(x);
		}
		else if(op == 'D')
		{
			cin >> k;
			if(!k) head = ne[head]; //特判,当k==0,删掉头结点
			remove(k - 1);
		}
		else
		{
			cin>> k >> x;
			add(k - 1,x); //第k个输入的数,下标为k-1
		}
	}
	 for(int i = head;i != -1;i = ne[i] ) cout<<e[i]<<' '; //遍历链表
	 cout<<endl;
	 return 0;
}

二.双链表

双链表:可以优化某些问题

 1.双链表的基本操作

  1.插入:在下标为k的右边插入一个点

代码实现

#l[N] 表示某个节点的左节点
#r[N] 表示某个节点的右节点


// 在下标是k的右边,插入x 
void add(int k,int x){
	e[idx] = x;
	r[idx] = r[k]; //当前点idx右边指向k的右边
	l[idx] = k;
	l[r[k]] = idx; //r[k]的左边指向idx
	r[k] = idx;
} 

注意必须先调用l[r[k]],再修改r[k]

2. 倘若要在下标为k的左边插入x ,相当于在 l[k] (k左边的一个点)的右边插入一个点 ,将k改成l[k]即可

void add(int l[k],int x){}

得出结论,双链表的插入只用实现一个即可

3. 删除:删掉下标为k的点

//删除第k个点 
void remove(int k){
	r[l[k]] = r[k]; //k左边的右边指向k的右边
	l[r[k]] = l[k]; //k右边的左边指向k的左边
}

yxc大佬YYDS!!!!!!!!!!!!!!!!!!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值