数据结构(一)链表(数组模拟版)

本文介绍了如何使用数组模拟单链表和双链表,包括结点值存储、指针管理和基本操作如初始化、插入、删除。在单链表部分,通过两个数组e和ne来存储结点值和next指针。而在双链表部分,增加了一个l数组来记录左侧结点,插入和删除操作得到详细说明。代码实现涵盖双链表的五种核心操作。
摘要由CSDN通过智能技术生成

一、单链表

单链表作用:常用于作为邻接表,可以存储树或图

数组模拟单链表方法:

创建两个数组,e[N]用来存每一个结点的value值,ne[N]用来存每一个结点的next指针,空节点的ne值为-1,两个数组是通过下标关联起来的,都是int型head表示头指针,指向链表头,链表空时为-1,idx表示当前用到了哪个点,如下图所示:

 初始化、插入、删除基本操作如下:

#include <iostream>

using namespace std;

const int N = 1e5 + 10;
//head表示头结点的下标
//e[i]表示结点i的值
//ne[N]表示结点i的next指针
//idx表示当前用到了哪一位 
int head, e[N], ne[N], idx;

//链表初始化 
void init(){
	head = -1;//空链表 
	idx = 0;//可用是第0位 
}
//头插法 
void add_to_head(int x){
	e[idx] = x;//赋值 
	ne[idx] = head;//idx的下一位指向头结点的next 
	head = idx;//头结点的next指向idx 
	idx++;//此位已用,当前可用即为下一位 
}
//一般情况插入,将x插到下标是k的点后面
void add(int k, int x){
	e[idx] = x;
	ne[idx] = ne[k];
	ne[k] = idx;
	idx++;
} 
//将下标是k的下一位删除
void remove(int k){
	ne[k] = ne[ne[k]];
} 
int main() {
	init();
	int m;
	cin >> m;
	while(m--){
		int k, x;
		char op;//操作
		cin >> op;
		//头插 
		if(op == 'H'){
			cin >> x;
			add_to_head(x); 
		} 
		//删除 
		else if(op == 'D'){
			cin >> k;
			if(k == 0) head = ne[head];//删头结点
			else remove(k-1); 
		}
		//插入
		else{
			cin >> k >> x;
			add(k-1, x);
		} 
	}
	for(int i=head;i!=-1;i=ne[i]) cout << e[i] << " ";
	cout << endl;
	return 0;
}

二、双链表

用三个数组,e[N]用来存储结点的数值,l[N]用来表示该结点左边的结点的地址,r[N]用来表示该结点右边的结点的地址。

头结点和尾结点简单起见,head用0表示,tail用1表示,初始化很好理解,写法为:

//初始化
void init(){
    r[0] = 1;//头结点右边是尾结点
    l[1] = 0;//尾结点的左边是头结点
    idx = 2;//从2开始
 }

在下标为k的结点右边插入一个新的结点的写法为:

//在下标为k的结点右边插入一个新的结点
 void add(int k, int x){
    e[idx] = x;//赋值
    r[idx] = r[k];
    l[idx] = k;
    //以下两步不能颠倒
    l[r[k]] = idx;
    r[k] = idx;
    idx++;
}

删除下标为k的结点的写法为:

//删除下标为k的结点
void remove(int k){
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}

都很好理解!y总yyds!

值得注意的是,由于双链表的初始化用了head和tail充当头结点和尾结点,因此后续插入的第k个数下标应该为k+2-1=k+1!最后双链表的输出也不包括head和tail!

双链表五个操作AC代码如下:

#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;
int head, e[N], l[N], r[N], idx;
//初始化
void init(){
    r[0] = 1;//头结点右边是尾结点
    l[1] = 0;//尾结点的左边是头结点
    idx = 2;//从2开始
 }
 //在下标为k的结点右边插入一个新的结点
 void add(int k, int x){
    e[idx] = x;//赋值
    r[idx] = r[k];
    l[idx] = k;
    //以下两步不能颠倒
    l[r[k]] = idx;
    r[k] = idx;
    idx++;
}
//删除下标为k的结点
void remove(int k){
    r[l[k]] = r[k];
    l[r[k]] = l[k];
}

int main(){
    init();
    int m;
    cin >> m;
    while(m--){
        int k, x;
        string op;//操作
        cin >> op;
        if(op == "L"){
            cin >> x;
            add(0, x);//最左边插入
        }
        else if(op == "R"){
            cin >> x;
            add(l[1], x);//最右边插入
        }
        else if(op == "D"){
            cin >> k;
            remove(k+1);//0和1用来初始化,因此第k个操作的下标应为k+2-1=k+1
        }
        else if(op == "IL"){
            cin >> k >> x;
            add(l[k+1], x);
        }
        else{
            cin >> k >> x;
            add(k+1, x);
        }
    }
    for(int i=r[0];i!=1;i=r[i]) cout << e[i] << ' ';
    cout << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值