数据结构
链表与邻接表: 树与图的存储
数组模拟单链表
链表中的每一个结点只有两个部分。我们可以用一个数组data来存储序列中的每一个数。那么每一个数的右边我们就需要再用一个数组right来存放序列中每一个数。

现在需要在8前面插入一个6,只需要将6直接存放在数组data的末尾data[10] = 6。接下来只需要将right[3]改为10,表示新序列中3号元素右边的元素存放在data[10]中。再将right[10]改为4,表示新序列中10号元素右边的元素存放在data[4]中。



#include<iostream>
using namespace std;
const int N = 100010;
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 --)
{
int k, x;
char op;
cin >> op;
if(op == 'H')
{
cin >> x;
add_to_head(x);
}
else if(op == 'D')
{
cin >> k;
if(!k) head = ne[head];
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;
}
10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6
// 6 4 6 5
数组模拟单链表
const int N = 100010;
int head,e[N],ne[N],idx;//所有idx表示的是节点的下标,也就是索引,然后当前idx的值表示下一个插入的节点的索引是多少,或者说当前插入新的节点用到的下标是多少,e[N]表示
void init(){
head = -1;//用-1来表示null
idx = 0;//下标也可以从1开始,无所谓
}
//头插法 ,在head后面插入一个节点值为x的节点
void add_to_head(int x){
e[idx] = x;
ne[idx] = head;
head = idx ++;
}
//在索引是k的下一个位置插入x ,如果知道第k的元素的索引 那么后面那个元素删除和插入操作复杂度都是O(1)
void add_after_k(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx ++;
}
//删除在索引是k的下一个节点
void remove_after_k(int k){
ne[k] = ne[ne[k]];
}
//遍历一个单链表.固定模板
for(int i = head;i != -1;i = ne[i]) {
cout << e[i] << " ";
}
数组模拟双链表
const int N= 100010;
int m;
int e[N],l[N],r[N],idx;
//双链表的的插入应该先把新节点的左右指向先赋值好,然后其他操作都用新界点的左右指向来操作,这样就会方便
//应该这样不会考虑原来的指向指针丢失的问题
void init(){
//链表为空的初始化状态,head和tail可以用0 1来代表,所以idx 应该从2开始
r[0] = 1,l[1] = 0;
idx = 2;
}
//在第k个元素的右边插入一个新元素,若想在k的左边插入元素直接调用add(l[k],x)就可以,或者重新实现一编逻辑
void addR(int k,int x){
e[idx] = x;
l[idx] = k;
r[idx] = r[k];
l[r[idx]] = idx;
r[k] = idx ++;
}
void addL(int k,int x) {
e[idx] = x;
r[idx]= k;
l[idx] = l[k];
l[k] = idx;
r[l[idx]] = idx ++;
}
//删除双链表中的第k个元素
void remove_k(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
void add_to_begin(int x){
e[idx] = x;
r[idx] = r[0];
l[idx] = 0;
r[0] = idx;
l[r[idx]] = idx ++;
}
void add_to_last(int x) {
e[idx] = x;
l[idx] = l[1];
r[idx] = 1;
r[l[idx]] = idx;
l[1] = idx ++;
}
数组模拟邻接表
const int N = 100010,M = 100010;//N 为最大节点数,M 为最大边数
int h[N],e[M],ne[M],w[M],idx;//
//加边操作模板
void add(int a,int b,int c){
//加入一条从a----->b,而且权值为c,将其看作单链表的操作会更好理解
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx ++;
}
数组模拟栈
const int N = 100010;
int stk[N],tt;//tt表示栈顶元素的索引,为0的时候表示没有元素
void push(int x){
stk[++ tt] = x;
}
//delete
void pop(){
tt --;//删除元素直接指针下移就行
}
int top(){
return stk[tt];
}
//判空
bool
数据结构与算法详解

本文深入探讨了数据结构如链表、栈、队列、树和图的存储方式,以及算法如KMP、Trie、并查集、堆、Hash表的应用技巧。通过具体实例介绍了数组模拟这些数据结构的方法。
最低0.47元/天 解锁文章
869

被折叠的 条评论
为什么被折叠?



