双向链表学习笔记
作者:互联网
双向链表学习笔记
啰嗦
双向链表
这是百度里给出的解释.
说的通俗一点,就是左右都连着元素的数据结构.(好像也不怎么通俗)
这次手打,不玩STL.
啰嗦完了,那就切入正题了.
双向链表
双向链表嘛,那就是长这个样子:
大家看看就好了.
定义(struct)
定义长这样:
struct Node{
int x;
Node *next,*pre;
}head,tail;
是什么意思呢?我们一个一个解释:
struct Node{
int x; //值.
Node *next,*pre; //next指向下一个节点,pre指向前一个节点.
}head,tail;//head是链表顶端元素,tail是链表末端元素(head和tail没有值,head.pre=tail.next=NULL)
看完了吧?我们继续.
插入一个数(addl与addr)
这是两个函数的代码:
void addl(Node *r,int x){ //在地址
Node *l=r->pre;
Node *zd=new Node{x,r,l};
l->next=zd;
r->pre=zd;
}
void addr(Node *l,int x){
Node *r=l->next;
Node *zd=new Node{x,l,r};
l->next=zd;
r->pre=zd;
}
注:出现警告是正常的,不用害怕(我也不知道为什么,能过就行了),如果有个别强迫症,如下代码也行
void addl(Node *w,int x){
Node *l=r->pre;
Node *zd=new Node;
zd->x=x;
zd->next=r;
zd->pre=l;
l->next=zd;
r->pre=zd;
}
void addr(Node *l,int x){
Node *r=l->next;
Node *zd=new Node;
zd->x=x;
zd->next=r;
zd->pre=l;
l->next=zd;
r->pre=zd;
}
现在就开始解释了.
注:x->y
就相当于(*x).y
.
先看如下图:
现在有一个\(a_4\) 想要插在\(a_3\) 与\(tail\)之间,那么我们应该把\(a_3\) 的\(next\)指向\(a_4\) ,把\(tail\)的\(pre\)指向\(a_4\) ,即(可能画的有点丑):
然后再把\(a_4\) 的\(next\)指向\(tail\),\(pre\)指向\(a_3\) 就好了.我就不画了(画太丑了).
这里再补充一下:
new:新建一个节点(类型自定),返回该节点的地址.
这下应该都懂了吧?先练练手!
练习1
题目描述
创建一个新链表,往里面添加\(n\)个元素,请在最后分别正向与反向输出链表.
输入
第一行\(n\),表示初始链表n个点.
第二行\(n\)个数字,表示链表.
输出
第一行正向输出链表.
第二行反向输出链表.
input
5
1 2 3 4 5
output
1 2 3 4 5
5 4 3 2 1
思考
这题的重点就是正向反向输出链表.
那么我们可以像循环一样输出,也可以用一个指针\(while\)输出,我选择的是\(while\).
那么起点与终点该怎么设置呢?我们再看原来那张图:
我们要从\(a_1\)出发,到达\(a_3\) .
但是我们没有\(a_1\)的确切地址,该怎么办?
往回看,\(head\)的\(next\)就指向\(a_1\) .
那么,起点就是\(head->next\).
但是终点可不是\(tail->pre\),而是\(tail\).
因为设置成\(tail->pre\)了话,到达\(a_3\)也就是\(tail->pre\)的时候就结束了循环.
代码如下:
void print1(){ //正向
Node *i=head.next;
while (i!=&tail) cout<<i->x<<" ",i=i->next;
cout<<"\n";
}
void print2(){ //反向
Node *i=tail.pre;
while (i!=&head) cout<<i->x<<" ",i=i->pre;
}
代码
#include<bits/stdc++.h>
//#define int long long
using namespace std;
int n,x,m,y;
struct Node{
int x;
Node *next,*pre;
}head,tail;
void addl(Node *w,int x){
Node *t=w->pre;
Node *zd=new Node;
zd->x=x;
zd->next=w;
zd->pre=t;
t->next=zd;
w->pre=zd;
}
void delet(Node *qwq){
Node *t=qwq->pre;
Node *w=qwq->next;
w->pre=t;
t->next=w;
free(qwq);
}
Node *find(int x){
Node *k=head.next;
while (k->x!=x&&k!=&tail) k=k->next;
return k;
}
void print1(){
Node *i=head.next;
while (i!=&tail) cout<<i->x<<" ",i=i->next;
cout<<"\n";
}
void print2(){
Node *i=tail.pre;
while (i!=&head) cout<<i->x<<" ",i=i->pre;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
head.next=&tail; //把head和tail连起来可别忘了哦!
tail.pre=&head;
cin>>n>>m;
for (int i=1;i<=n;i++){
cin>>x;
addl(&tail,x);
}
print1();print2();
return 0;
}
(未完待续)
标签:Node,pre,zd,笔记,next,链表,tail,双向 来源: https://www.cnblogs.com/Sity-Hugh/p/16577582.html