(1)在顺表表中,如果是头插/删的时间复杂度是O(1);尾插/删的时间复杂度是O(N)
(2)增容一般是呈2倍的增长,势必会有一定的空间浪费。比如:申请了50个空间,只用了两个?(链表可以解决空间浪费的问题)
这一章节的内容是关于单链表。
文章目录
1. 链表
链表也是线性表的一种。我们仍然从物理结构和线性结构来分析
(1)物理结构(真实):不是线性
(2)线性结构(想象):线性
重点:链表是由一个一个的结点连接起来的。每次创建一个结点,不存在浪费的情况。
一个结点里面存储的是:数据+下一个结点的地址。
链表里的结点,它们的地址不是连续的,而是靠(存储的地址)连接起来的。
(3)在链表中,没有增容的概念。如果要增加数据,直接再申请一个结点大小的空间即可。
2. 单链表
1. 单链表的概念
单链表的全称是”不带头,单向,不循环链表“。
- 单链表的定义:在.h里
(1)创建链表—>在test.c里
这个方法只是示范一下,平常创建链表并不会像这么麻烦。
在初始情况下,链表是空链表,只有一个结点,指向NULL,之后尾插即可达到申请结点的结果。
//这个是写在test.c的内容
#include"SLTNode.h"
//创建链表
void creatListNode()
{
//使用malloc记得写头文件stdlib
SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 1;
SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
node2->data = 2;
SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
node3->data = 3;
node1->next = node2;
node2->next = node3;
node3->next = NULL;
}
int main()
{
creatListNode();
return 0;
}
(2)打印链表出来看看
2. 单链表的实现
2.1 尾插
不管是头插还是尾插,都需要再申请一个结点大小的空间,所以可以将它封装为一个函数,之后调用即可。
尾插比较简单,有两种可能。
1.链表不为空。最后一个结点的next指向NULL,我们只需将 (最后一个结点的next) 指向 (想插入的结点的地址newnode) 即可。
2.链表为空,就不用找结点了。在刚开始时,我们创建了链表struct SLTNode,这是空链表,只有一个头结点(phead)指向NULL,我们将phead->next指向newnode即可
注意在尾插时传过去的是地址,这样形参的改变可以改掉实参。
//SLTNode.h里的内容
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//定义链表的结点
typedef int SLTDataType;
typedef struct SLTNode
{
SLTDataType data;
struct SLTNode* next;
}SLTNode;
//申请新结点
SLTNode* SLTBuyNode(SLTDataType x);
//尾插
void SLTPushBack(SLTNode** pphead,SLTDataType x);
//打印链表
void SLTPrint(SLTNode* phead);
//SLTNode.c里面的内容
#include"SLTNode.h"
//用于打印链表的函数的定义
void SLTPrint(SLTNode* phead)
{
SLTNode* pcur = phead;
while (pcur)
{
printf("%d(地址:%p) -> ",
pcur