1 线性表
1.1 线性表(Linear List)定义
由同类型数据元素构成的有序序列的线性结构
线性表是逻辑上的定义,不是物理存储上的定义
1.2 线性表的抽象数据类型描述
这里是抽象描述(数据对象集,有关操作)
1.3 线性表的存储
按照顺序结构存储的线性表称作“顺序表”,可以理解为数组。
按照链式结构存储的线性表称作“链表”
2 两种存储结构
2.1 顺序存储结构
借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系。
2.1.1 初始化
- 要提前申请好足够大的存储空间
- 要记录顺序表的长度
例子代码
/*
* @Brief: 循序表
* @Author:
* @Date: 2021-01-29
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef struct table
{
int* head;
int size; // 总长度
int length; // 当前长度
};
// 顺序表初始化
table initTable(int ll){
table ans;
ans.head = (int*)malloc(ll * sizeof(int));
if(!ans.head){
printf("init error\n");
exit(0);
}
ans.size = ll;
ans.length = 0;
return ans;
}
int main(){
table LinearList = initTable(10);
// add element to table
for(int i = 0 ; i < LinearList.size; i++){
LinearList.head[i] = i;
LinearList.length++;
}
// display
for(int i = 0 ; i < LinearList.length; i++){
cout << LinearList.head[i] << endl;
}
return 0;
}
2.1.2 基本操作
插入
指定位置后边的数据元素都依次向后移动,腾出一个空位后把插入元素放进来。
删除
找到目标元素,它后边的元素依次向前移动一个位置,将其覆盖掉。
查找
可以用多种查找算法,比如二分、插值。
修改
先查找到该元素,然后直接修改。
2.2 链式存储结构
借助指示元素存储地址的指针表示数据元素之间的逻辑关系。
2.2.1 单向链表
插入
在第i个位置上插入新节点。
构造一个新节点B,B先指向C(插入之前的第i个节点),再用A(插入之前的第i-1个节点)指向B。
删除
删除第i个节点
先找到第i-1个节点(节点P),用临时变量S指针指向第i个节点,然后节点p指向S的下一个节点(指第i+1个节点),防止内存泄漏,要free掉S的空间。
查找
从头遍历。
分为按序号查找和按值查找。
求表长度
遍历
2.2.2 双向链表
2.2.3 循环链表
2.2.4 双向循环链表
向前、向后都形成一个环。
2.2.5 块状链表
广义表的基本概念
广义表是线性表的推广,其实是一个多重链表,一个线性表要么存储不可再分的数据元素(例如数字1、字符a),要么存储可再分的数据元素(例如存储数组)。但是广义表,可以同时存储这两种数据元素(不可再分元素和可再分元素)。
广义表中不可再分的元素称为原子,可再分的元素称为子表。
当广义表非空的时候,第一个元素(原子或子表)叫作表头,其余所有元素叫作表尾(表尾一定是一个广义表)。如果一个表中只有一个元素,那么他的表尾是空表。
如果一个广义表非空,那么他一定就有表头和表尾。