链表基础知识
1.链表概念
链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
2.链表的类型
单链表
上面说的这种链表就是单链表,要区分单链表和stl
中List容器的区别。区别整理在后面。
双链表
另一种叫做双链表。单链表中的指针域只能指向节点的下一个节点。
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
双链表 既可以向前查询也可以向后查询。
循环链表
循环链表,顾名思义,就是链表首尾相连。
循环链表可以用来解决约瑟夫环问题。
3.链表存储方式
数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
链表是通过指针域的指针链接在内存中各个节点。
所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
图上这个链表起始节点为2, 终止节点为7, 各个节点分布在内存的不同地址空间上,通过指针串联在一起。
4.链表ListNode
与STL中list容器的区别
listNode
和STL
中的list
容器在设计和使用上有一些重要的区别:
- 设计原理:
listNode
通常是一个简单的自定义数据结构,通常包含数据和指向其他节点的指针。这是链表数据结构的基础,它允许我们添加、删除和搜索节点。而STL
中的list
是一个双向链表容器,它不仅提供了基础的链表操作,还提供了大量的其他功能,如排序、逆序、合并等。 - 接口和操作:
listNode
通常需要用户自己实现所有的操作,如添加节点、删除节点、搜索节点等。这需要对链表数据结构有一定的理解。而list
提供了一套丰富的接口,可以很方便地进行各种操作,如插入、删除、排序、查找等,而无需用户了解链表的底层实现。 - 容器特性:
STL
的list
是一个容器类,可以存储任何类型的元素,例如,你可以有一个list<int>
或list<string>
等。而**listNode
通常是针对特定类型的元素设计的,如果要存储其他类型的元素,可能需要重新设计listNode
。** - 性能:在某些操作上,
list
和listNode
的性能会有所不同。例如,如果你需要频繁地在链表中间插入和删除元素,list
可能会比listNode
更快,因为list
是双向链表,可以更快地找到插入和删除的位置。然而,如果你需要频繁地访问链表的头部和尾部元素,listNode
可能会更快,因为它可以直接访问这些元素,而list
需要遍历整个链表。 - 内存使用:一般来说,由于
list
提供了更多的功能和接口,它可能会使用更多的内存。但这取决于具体的实现和使用情况。
总的来说,listNode
和list
各有其优点,根据你的具体需求和应用场景,你可以选择使用最适合的一个。
5.链表的定义方式
链表节点定义方式:
// 单链表的定义
struct ListNode{
int val; //节点上储存的元素
ListNode *next; //指向下一个节点的指针
ListNode(int x): val(x),next(NULL){
//节点的构造函数
}
}
自定义构造函数与不提供构造函数的区别:
通过自己定义构造函数初始化节点:
ListNode* head = new ListNode(5); //定义指针,指向链表对象(虚拟头节点用法)
使用默认构造函数初始化节点:
ListNode* head = new ListNode();
head->val = 5;
所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值!