一、单链表
单链表作用:常用于作为邻接表,可以存储树或图。
数组模拟单链表方法:
创建两个数组,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;
}