概述
链表存储结构是一种动态数据结`构,其特点是它包含的数据对象的个数及其相互关系可以按需要改变,存储空间是程序根据需要在程序运行过程中向系统申请获得,链表也不要求逻辑上相邻的元素在物理位置上也相邻,它没有顺序存储结构所具有的弱点。以数组储存为例,当我们向一个数组中插入某个数时,后面的数也要随之向后移动以空出位置,显然这样非常费时,但若是向链表中插入,那么仅需开辟一个新的空间来存储然后链接前后两数。
链表是由节点构成:表头+结点+表尾
节点:就是一个特殊的结构体,此结构体由2部分组成,一部分是数据域,另一部分是指针域;数据域(该结点数据);指针域(下一结点的首地址)
数据域:存储结点本身的数据,信息;
指针域:保存下一个结点的首地址(指向后继结点的指针)
本文我们以数组来实现链表
单链表
例题
#include<iostream>
using namespace std;
int arr[1000001];
int r[1000001];
int main()
{
int n;
cin >> n;
int head = -1, rear = 0;//head表示第一个数的位置,rear表示其后一个位置(因为最后是反向输出)
while (n--)
{
char a;
int x, y;
cin >> a;
if (a == 'H')//搁后边插入数(因为最后是反向输出)
{
cin >> x;
arr[rear] = x;
r[rear] = head;//当前位置指向下一个位置
head = rear;//更新头头的位置
rear++;//指针向后移一个
}
else if (a == 'I')//在第x插入的数后边插入y
{
cin >> x >> y;
arr[rear] = y;
r[rear] = r[x - 1];
r[x - 1] = rear;
rear++;
}
else if (a == 'D')//删除第x个插入的数后边的数
{
cin >> x;
if (!x)//首尾缩一格
{
head = r[head];
}
else
r[x - 1] = r[r[x - 1]];//跳过后边的数指向下一个数的位置
}
}
for (int i = head; i !=-1; i=r[i])//反向输出
cout << arr[i] << " ";
return 0;
}
双链表
例题
#include <iostream>
using namespace std;
const int N = 100010;
int arr[N], l[N], r[N], idx;
//初始化
void init() {
//0表示左端点,1表示右端点
r[0] = 1;
l[0] = 0;
idx = 2;
}
//在第k点的右边插入x
void addright(int k, int x) {
arr[idx] = x;//将x存入当前下标的数值数组中
r[idx] = r[k];//当前下标的后继为k的后继
l[idx] = k;//当前下标的前驱为k
l[r[k]] = idx;//k的后继节点的前驱为idx
r[k] = idx++;//k的后继节点为idx,idx++
}
//在k点的左边插入x
void addleft(int k, int x) {
addright(l[k], x);
}
//删除第k个点
void remove(int k) {
r[l[k]] = r[k];//k的前驱的后继为k的后继
l[r[k]] = l[k];//k的后继的前驱为k的前驱
}
//最左端插入数x
void addhead(int x) {
addright(0, x);//在0后面插入x
}
//最右端插入数x
void addtail(int x) {
addright(l[1], x);
}
int main() {
int m;
init();
cin >> m;
int k, x;
while (m--) {
string op;
cin >> op;
if (op == "L") {
cin >> x;
addhead(x);
}
else if (op == "R") {
cin >> x;
addtail(x);
}
else if (op == "D") {
cin >> k;
remove(k + 1);
}
else if (op == "IL") {
cin >> k >> x;
addleft(k + 1, x);
}
else {
cin >> k >> x;
addright(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i]) {
cout << arr[i] << ' ';
}
return 0;
}