链表的定义:
链表是一种常见的数据结构,由一系列节点(Node)组成,每个节点包含两个部分:数据域(Data Field)和指针域(Pointer Field 或 Link Field)。数据域用于存储节点的数据,而指针域用于存储指向下一个节点的引用(即地址或链接)。链表通过指针将这些节点连接起来,从而形成一个序列。
常见的链表有单向链表(Singly Linked List)、双向链表(Doubly Linked List)、循环链表(Circular Linked List)等,我们今天练习的是双向链表。
特性:
双向链表
- 每个节点包含两个指针,一个指向下一个节点,另一个指向前一个节点。
- 允许从任意节点向前或向后遍历。
指针
指针是编程语言中的一种数据类型,它存储了内存中的一个地址,这个地址指向另一个变量的值。换句话说,指针是一个变量,其内容是另一个变量的内存地址,而不是数据值本身。通过使用指针,程序可以直接访问和操作内存。
- 指针类型:指针变量有一个类型,这个类型指明了它所指向的数据的类型。例如,一个指向整数的指针类型在
C
语言中表示为int*
。 - 指针变量:指针本身是一个变量,它存储了一个地址值。这个地址值是指向另一个变量的内存地址。
- 解引用:通过指针可以访问它所指向的变量的值。这个过程通常称为
解引用
或间接访问
。在C语言中,解引用是通过在指针变量前加上星号(*)
来实现的。 - 地址运算:指针可以进行一些特殊的运算,比如加法、减法和比较运算。这些运算通常基于指针所指向的数据类型的大小来进行。
- 空指针:一个指针变量可以被赋值为
NULL
(在C
和C++
中)或nullptr
(在C++11
及以后版本中),以表示它不指向任何有效的内存地址。 - 野指针:一个未初始化或已被释放但仍被使用的指针被称为
野指针
。野指针
的使用是危险的,因为它们可能指向无效的内存地址,导致程序崩溃或不可预测的行为。 - 多级指针:一个指针可以指向另一个指针,从而形成多级指针。多级指针在处理复杂的
数据结构
或进行底层内存管理时非常有用。
思路描述
目标反向输出数组,即链表需要有指向上一个节点的指针。
初级题目,直接开干
代码实现
既然是写代码,头文件和main函数自然是不能少的
#include<bits/stdc++.h>
#define int long long // 宏命令,可省略
using namespace std;
signed main(){ // 因为将int定义为“long long”,mian函数返回值类型要改变
}
不过,写链表还要在中间插入一个结构体
,话不多说,直接上:
#include<bits/stdc++.h> // C++万能头文件
#define int long long // 宏命令,可省略
using namespace std;
struct l{ // struct是结构体的关键字,l是结构体的名称(类似变量名)
int n; // 链表中存储数据的变量
l *shang; // 指向上一个节点的指针
l *xia; // 指向下一个节点的指针
};
signed main(){ // 因为将int定义为“long long”,mian函数返回值类型要改变
}
接着是输入数据,处理指针的时候,过程比较复杂,尽量理解吧
注意:用指针访问结构体时要用->
,名称访问用点.
即可
int n;
cin >> n;
l *lian1 = new l; // 定义新指针,指向的结构体作为链表的第一个节点
cin >> lian1 -> n; // 输入第一个节点的数据
for(int i = 0; i < n - 1; ++i){
l *lian2 = new l; // 定义新指针,指向链表的下一个节点
cin >> lian2 -> n; // 输入数据
lian2 -> shang = lian1; // 赋值下一个节点指向上一个节点的指针
lian1 -> xia = lian2; // 赋值上一个节点指向下一个节点的指针
lian1 = lian2; // 更换节点
}
此时可以发现,最开始定义的指针lian1
是链表的倒数第一个节点,可以用箭头->
访问数据输出,上代码:
记得输出空格
while(lian1 != NULL){
cout << lian1 -> n <<" "; // 输出
lian1 = lian -> shang; // 指向上一个节点
}
OVER!!!
最后,放完整代码:
#include<bits/stdc++.h> // C++万能头文件
#define int long long // 宏命令,可省略
using namespace std;
struct l{ // struct是结构体的关键字,l是结构体的名称(类似变量名)
int n; // 链表中存储数据的变量
l *shang; // 指向上一个节点的指针
l *xia; // 指向下一个节点的指针
};
signed main(){ // 因为将int定义为“long long”,mian函数返回值类型要改变
int n;
cin >> n; // 输入数组个数
l *lian1 = new l; // 定义新指针,指向的结构体作为链表的第一个节点
cin >> lian1 -> n; // 输入第一个节点的数据
for(int i = 0; i < n - 1; ++i){ // 循环输入数据
l *lian2 = new l; // 定义新指针,指向链表的下一个节点
cin >> lian2 -> n; // 输入数据
lian2 -> shang = lian1; // 赋值下一个节点指向上一个节点的指针
lian1 -> xia = lian2; // 赋值上一个节点指向下一个节点的指针
lian1 = lian2; // 更换节点
}
while(lian1 != NULL){
cout << lian1 -> n <<" "; // 输出
lian1 = lian1 -> shang; // 指向上一个节点
}
}
是的,链表的初级运用就这么水灵灵的学完了,来看看数据测试
输入:
10
0 1 2 3 4 5 6 7 8 9
输出:
9 8 7 6 5 4 3 2 1 0