线性表
- 相同数据类型
- 线性表基本操作:初始化、销毁、插入、删除、按值查找、按位查找、求表长、判空等(创销、增删改查),基本操作的输入一般是“&”引用的表,操作后原表会改变。
顺序表
- 顺序存储,按地址排列
- 顺序表特点:索引方便、存储密度高、拓展容量不方便,插入删除不方便 (需要依次后移或前移)
//静态分配(必须常数个空间)
int a[8];//占用空间 4*8 字节
//动态分配(根据实际变量分配空间)
//c语言
int len = 8;
int* a;
a = (int*) malloc(len * sizeof(int));
free(a);//变量用完后需要销毁
//c++
int* a = new int[len]
delete a;//用完销毁
note:
- 动态分配依旧不能随意改变分配的空间大小,但是可以通过另起一片空间,更换头指针的方式改变数组大小。
- 动态分配用完记得销毁。
- 循序表不方便增删,容量固定,链表不方便查找
单链表
- 每个节点包括数据域和指向下个节点的指针域
- 特点:不用连续空间,方便改变容量、不可索引
//代码仅作参考
//C语言
typedef struct ListNode {
int val;
struct ListNode* next;
}ListNode;
head = (ListNode*) malloc(sizeof(ListNode));
//C++
struct ListNode {
int val;
struct ListNode* next;
//初始化列表
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* head;
head->val = 1;
head->next = new ListNode(1);
//尾部插入1个
//遍历到尾部
ListNode* node = head;
while(node->next != nullptr)
node = node->next;
node->next = new ListNode(1);
//中间插入1个
//先建一个节点next指向node->next的节点,再把node->next指向新建的节点
ListNode* node = head;
for(int i = 0; i < 3; ++i)//按位查找
node = node->next;
node->next = new ListNode(1, node->next);
//循环头插(链表逆置)
ListNode* node = head;
ListNode* head1 = new ListNode(head->val);//定义一个新链表
while(node->next != nullptr) {
ListNode* node1 = new ListNode(node->next->val);
node1->next = head1->next;
head1->next = node1;
node = node->next;
}
//删除中间
ListNode* node = head;
for(int i = 0; i < 3; ++i)
node = node->next;
//删除node->next
ListNode* tmp = node->next;
node->next = node->next->next;
delete tmp;
note:
- 已知中间节点,如果要前插一个,则将已知节点复制给一个新建节点插入到已知节点后,然后更改已知节点,删除同理。
- 增删改查可以封装成函数,输入用引用格式可以实现改变原链表。
双链表
- 可以向前查找,两个节点之间是双向指针
- 一个节点包含数据域和前驱指针prior、后继指针next

//代码仅作参考
struct ListNode {
int val;
struct ListNode* prior;
struct ListNode* next;
//初始化列表
ListNode() : val(0), prior(nullptr), next(nullptr) {}
ListNode(int x) : val(x), prior(nullptr), next(nullptr) {}
ListNode(int x, ListNode *prior, ListNode *next) : val(x), prior(prior), next(next) {}
};
ListNode* head;
head->val = 1;
head->next = new ListNode(1);
//中间插入1个
//1、先建一个节点,prior指向node,next指向node->next的节点;
//2、node->next-prior指向新建的节点
//3、node->next指向新建的节点(2,3顺序不能换)
ListNode* node = head;
for(int i = 0; i < 3; ++i)//按位查找
node = node->next;
ListNode* tmp = new ListNode(1, node, node->next);
node->next->prior = tmp;
node->next = tmp;
//删除中间
ListNode* node = head;
for(int i = 0; i < 3; ++i)
node = node->next;
//删除node->next,更新前后节点指针,再删除
ListNode* tmp = node->next;
node->next->next->prior = node;
node->next = node->next->next;
delete tmp;
note:
- 表尾插入需要判断非空
循环链表
- 尾结点指向头节点
- 循环单链表也可以实现前节点的查找


//代码仅作参考
//初始化
ListNode* head;
head->val = 1;
head->prior = head;
head->next = head;
//判断表尾
ListNode* node = head;
while(node->next != head) {
node = node->next;
}
//插入和删除参考以上
静态链表
- 用数组的方式实现链表
- 每个节点包括数据域和游标
- 表尾的游标一般为-1
- 应用:操作系统的文件分配表FAT
//代码仅作参考
typedef struct ListNode {
int val;
int next;
}ListNode[10];//结构体数组
ListNode head;
for(int i = 0; i < 10; ++i) {
head[i]->next = -2;//还未分配节点
}
head[0]->val = 0;
head[0]->next = 3;
head[head[0]->next]->val = 1;//实际是head[3]
head[head[0]->next]->next = 8;
note:
- 增,删操作不用移动元素
- 不能随机存取,只能从前往后查找
- 容量固定
- 初始化静态链表的非节点位置处(还未分配节点的空间)时,游标可以统一自定义为一个数
本文详细介绍了线性表的基础操作,包括初始化、销毁、插入、删除等,以及顺序表、动态分配、单链表、双链表和循环链表的特点和示例。特别关注了动态分配的内存管理以及静态链表在操作系统文件分配表中的应用。
&spm=1001.2101.3001.5002&articleId=135515814&d=1&t=3&u=70f0696f2b914a00aa55d85ef01acf36)
8333

被折叠的 条评论
为什么被折叠?



