单链表
单链表的最大特点是可以将物理地址上不连续的数据连接起来,通过指针来对物理地址进行操作,实现增删改查等功能。单链表可以用来写邻接表,邻接表可以用来存储图和树。
链表中的数据是以结点来表示的,每个结点存两个值:数据+next指针,空集的下标为-1,单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素。
单链表结点中只有一个只指向后继的指针,使得单链表只能从头结点开始一次顺序的先后遍历。要访问某个结点的前驱结点(插入删除操作时),只能从头开始遍历,访问后继节点的时间复杂度为O(1),访问前驱结点的时间复杂度为O(n)。
举例:用单链表储存一串数3,5,7,9,11,13.(数据e[i],next指针ne[i],结点下标idx)
单链表的简单操作
- 在一个结点后插入一个结点
- 清除某个结点
将该结点的next指针指向下下一个结点
#include<iostream>
using namespace std;
const int N = 100005;
//head 是头结点的下标
//e[i] 是i结点的值
// ne[i] 是i的下一个结点的地址
//idx 储存当前结点的地址
int head, e[N], ne[N], idx;
//初始化
void init()
{
head = -1;//head 头结点为空(为空的结点的下标都用-1表示)
idx = 0;//单链表初始化 ,idx从0开始分配
}
//将x插入到头结点
void add_to_head(int x)
{
e[idx] = x,ne[idx] = head,head = idx,idx ++;
}
//在k结点后插入一个x
void add(int k,int x)
{
e[idx] = x;//新结点赋值
ne[idx] = ne[k];//新结点的next指针为下标为k的结点的next指针
ne[k] = idx;//将下标为k的结点的next指针指向新节点的下标
idx++;
}
//删除下标是k的结点的后面一个结点
void remove(int k)
{
ne[k] = ne[ne[k]];//下标为k的结点的next下标指向它的下下一个结点
}
int main()
{
init();
int x;
cin >> x;
add_to_head(x);//在头结点 插入一个x
for(int i = head;i != -1;i = ne[i])
cout << e[i] <<' ';
cout << endl;
int k1,x1;
cin >> k1 >>x1;
add(k1,x1);//在下标为k1的结点后面插入一个x1
for(int i = head;i != -1;i = ne[i])
cout << e[i] <<' ';
cout << endl;
int k2;
cin >> k2;
remove(k2);//清除下标为k2的结点的后面一个结点
for(int i = head;i != -1;i = ne[i])
cout << e[i] <<' ';
cout << endl;
return 0;
}
双链表
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有 两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
举例:存储下标和数据分别为1和3,2和4,3和5的双链表。
双链表的简单操作
- 删除一个结点
- 插入一个结点
#include<iostream>
using namespace std;
const int N = 100005;
//e[i]表示下标为i的结点的值
//l[i]表示下标为i的结点的左结点的值
//r[i]表示下标为i的结点的右结点的值
//idx表示该结点的下标
int e[N],l[N],r[N],idx;
//初始化
void init()
{
r[0] = 1;//初始化下标0和1为双列表的两个边界
l[1] = 0;
idx = 2;//0和1的下标已经被占用,idx从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)
{
l[r[k]] = l[k];
r[l[k]] = r[k];
}
int main()
{
init();
int k,x;
cin >> k >> x;
add(k,x);
for(int i=r[0];i!=1;i=r[i])
cout << e[i] << ' ';
cout << endl;
int k1;
cin >> k1;
remove(k1);
for(int i=r[0];i!=1;i=r[i])
cout << e[i] << ' ';
cout << endl;
return 0;
}