其他分享
首页 > 其他分享> > 双向链表学习笔记

双向链表学习笔记

作者:互联网

双向链表学习笔记


啰嗦

双向链表
这是百度里给出的解释.
说的通俗一点,就是左右都连着元素的数据结构.(好像也不怎么通俗)
这次手打,不玩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