数据结构学习笔记(一)—— 链表
(先在这里悄悄打个小广告 !^_^)
我看的是青岛大学王卓老师的数据结构视频,真的讲的非常好,每个点都讲得很仔细
B站链接:数据结构与算法基础(青岛大学-王卓)
链表
链表是一种很基础的数据结构,也可以利用链表构造其他的高级数据结构,掌握其中的一些思想也会方便学习之后的高级数据结构
一、基本结构与思想
传统的存储方式很容易想到用数组来实现。
用数组存储数据优点有很多比如:
- 创建起来比较方便
- 因为每个元素存储在连续的一片内存空间上,这样读取某个特定位置的元素就可以通过基地址+偏移量的方式很快的取出来
但是相应的缺点也是存在的
- 有时内存中没有大片的连续内存空间,就存不了较大规模的元素
- 要从数组中删除一个元素,就需要将其后面的元素一个一个向前搬移一格,会浪费大量的时间
因此就有了链表这样的一种思路,即每个元素不仅存储自身的信息,还存储一个指针,指向它的下一个元素,这样只要拿到了这个元素,就可以根据它的下一个元素指针找到下一个元素存放的内存位置。
最后一个元素之后没有元素了,所以将这个元素的下一个元素指针指向一个空值NULL
就像C语言声明数组一样,数组名表示了数组的首地址,链表也可以声明一个指针,指向链表的第一个元素,这样拿到这个指针就可以依次访问到数组中的各个元素了
拓展
在创建一个链表时可以把第一个节点作为头节点,在其中存储链表相关的信息。
二、C语言实现
1.链表结构体
每个链表元素我们称之为节点,每个节点包含两个成员,存储自身信息的数据域,存储下一个元素位置的指针域
typedef struct Lnode{
int val;
struct Lnode *next;
}Lnode, Linklist;
2.错误宏定义
宏定义内容 | 代表含义 | 值 |
---|---|---|
INDEX_OVERFLOW | 所给定位置超出链表范围 | -1 |
LINKLIST_EMPTY | 链表为空 | 400 |
#define INDEX_OVERFLOW -1
#define LINKLIST_EMPTY -400
3.链表相关方法
初始化链表
判断链表是否为空
在链表末尾添加元素
查找链表指定位置的值
查找指定值在链表中出现的位置, 返回第一次出现的下标
修改指定位置元素的值
在指定位置之后插入元素
删除指定位置元素
打印链表
1.初始化链表
将新建立的链表下一个元素指向NULL 我是使用将第一个元素节点作为头节点,在其中存储链表的长度这一信息/*
* 初始化链表
* @param {Linklist *L}
* @rerurn {void}
*/
void initLinkList(Linklist *L){
L->val = 0;
L->next = NULL;
return;
}
2.判断链表是否为空
/*
* 判断链表是否为空
* @param {Linklist *L}
* @rerurn {int (1-空 0-非空)}
*/
int isLinkListEmpty(Linklist *L){
if(L->next) return 0;
return 1;
}
3.在链表末尾添加元素
/*
* 在链表末尾添加元素
* @param {Linklist *L,
* int num}
* @rerurn {void}
*/
void addLinkListTail(Linklist *L,int num){
Lnode *newLnode = (Linklist *)malloc(sizeof(Lnode));
newLnode->val = num;
newLnode->next = NULL;
Linklist *p = L;
while(p->next){
p = p->next;
}
p->next = newLnode;
L->val++