IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构初阶 —— 线性表 -> 正文阅读

[数据结构与算法]数据结构初阶 —— 线性表

目录

一,线性表

?二,顺序表

顺序表的分类

顺序表缺陷

试题

三,链表

链表的分类(总共可分为八种)

单链表(单向无头不循环)

双向链表

顺序表和链表的区别

备注


一,线性表

  • 具有相同特性的数据元素的有限序列;
  • 在逻辑上是线性结构(是连续的一条直线),但在物理结构上并不一定是连续的;
  • 线性表在物理上存储时,通常以数组链式结构的形式存储;
  • 常见的线性表:顺序表、链表,栈、队列、字符串等;

?

?二,顺序表

  • 用一段物理地址连续的存储单元,依次存储数据元素的线性结构;
  • 一般情况下采用数组存储,在数组 上完成数据的增删查改;

顺序表的分类

  • 静态顺序表:使用定长数组存储元素;
  • 动态顺序表:使用动态开辟的数组存储;
//静态顺序表,顺序表的静态存储
#define N 7 
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType data[N]; //定长数组
	size_t size; //有效数据个数
}SeqList;
//动态顺序表,顺序表的动态存储
typedef int SLDataType;

typedef struct SeqList
{
	SLDataType* data; //指向动态开辟的数组
	size_t size; //有效数据个数
	size_t capicity; //容量空间(涉及扩容)
}SeqList;

接口实现

  • 由于静态顺序表,大小固定,现实中一般使用动态顺序表,大小可调整;
// 基本增删查改接口
// 顺序表初始化
void SeqListInit(SeqList* psl);

// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);

// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);

// 顺序表尾删
void SeqListPopBack(SeqList* psl);

// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);

// 顺序表头删
void SeqListPopFront(SeqList* psl);

// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x);

// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);

// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);

// 顺序表销毁
void SeqListDestroy(SeqList* psl);

// 顺序表打印
void SeqListPrint(SeqList* psl);

注:完整接口实现代码路径

顺序表缺陷

  • 增容需申请新空间,还可能需拷贝数据和释放旧空间,会有不小的消耗;
  • 增容一般为2倍增容,会有一定空间浪费;
  • PushBack/Insert,时间复杂度为O(N),效率较低;

试题

三,链表

  • 在物理存储结构上非连续、非顺序的;
  • 数据元素的逻辑顺序是通过链表中的指针链接次序实现的 ;

链表的分类(总共可分为八种)

  • 单向或双向链表
  • 带头或不带头链表(哨兵位)
  • 循环或不循环链表

单链表(单向无头不循环)

  • 结构简单,一般不会单独存数据,笔试、面试较多;
//单链表(无头单向不循环)
typedef int SLDataType;

typedef struct SListNode
{
	SLDataType data;
	struct SListNode* next;
}SListNode;

接口实现

//基本增删查改接口
//动态申请空间,生成一个节点
SListNode* BuySListNode(SLDataType x);

//单链表尾插
void SListNodePushBack(SListNode** pphead, SLDataType x);

//单链表头插
void SListNodePushFront(SListNode** pphead, SLDataType x);

//单链表尾删
void SListNodePopBack(SListNode** pphead);

//单链表头删
void SListNodePopFront(SListNode** pphead);

//单链表查找,先查找根据返回位置进行修改(无需在增加修改接口)
SListNode* SListNodeFind(SListNode* phead, SLDataType x);

//单链表指定位置前插入,先查找在根据返回位置插入(插入时还需遍历链表效率低)
//单链表不适合在指定位置前面插入
void SListNodeInsertBefore(SListNode** pphead, SListNode* pos, SLDataType x);

//单链表指定位置后插入,先查找在根据返回位置插入
void SListNodeInsertAfter(SListNode* pos, SLDataType x);

//单链表指定位置删除,先查找在根据返回位置删除(删除时还需遍历链表效率低)
//单链表不适合在指定位置删除
void SListNodeErase(SListNode** pphead, SListNode* pos);

//单链表指定位置后删除
void SListNodeEraseAfter(SListNode* pos);

//单链表节点释放
void SListNodeDestroy(SListNode** pphead);

//单链表打印
void SListNodePrint(SListNode* phead);

//单链表节点个数
int SListNodeSize(SListNode* phead);

//是否为空链表
bool SListNodeEmpty(SListNode* phead);

注:完整接口实现代码路径

试题

判断链表是否带环

?分析:假设fast比slow快一倍,则L=M

?\frac{m+n}{i*C+n} = \frac{1}{2}? ?或? ?\frac{m-n}{i*C-n} = \frac{1}{2}

?推导出:

L = i*C - \left ( m+n \right ) = i*C - X? 或

L = i*C - \left ( m-n \right ) = i*C - X

?结论

头节点入环起始节点之间的节点数等于相遇节点入环起始节点之间的节点数!

即,一指针从头走,一指针从相遇节点走,每次均走一步,最终会在入环节点相遇;

双向链表

  • 带头双向循环链表,结构最复杂,一般用于单独存储数据;
  • 结构优势明显,实际使用的数据结构;

//双向链表
typedef int SLDataType;

typedef struct SListNode
{
	struct SListNode* prev;
	struct SListNode* next;
	SLDataType data;
}SListNode;

接口实现

//基本增删查改接口
//初始化链表,会创建头节点(哨兵)
void SListInit(SListNode** pphead);

//链表尾插
void SListPushBack(SListNode* phead, SLDataType x);

//链表尾删
void SListPopBack(SListNode* phead);

//链表头插
void SListPushFront(SListNode* phead, SLDataType x);

//链表头删
void SListPopFront(SListNode* phead);

//查找节点
SListNode* SListFind(SListNode* phead, SLDataType x);

//指定位置前插入
void SListInsert(SListNode* pos, SLDataType x);

//指定位置删除
void SListErase(SListNode* pos);

//打印链表
void SListPrint(SListNode* phead);

//释放链表节点
void SListDestroy(SListNode* phead);

//求链表的节点数
size_t SListSize(SListNode* phead);

//判断是否为空链表
bool SListEmpty(SListNode* phead);

注:完整接口实现代码路径

顺序表和链表的区别

储存空间:

  • 顺序表物理上一定连续;
  • 链表逻辑上是连续的,物理上不一定连续;

随机访问(下标访问):

  • 顺序表,支持,O(1);
  • 链表,不支持,O(N);

任意位置插入或删除元素:

  • 顺序表,可能需要移动元素,效率低,O(N);
  • 链表,只需修改指针方向(带头双向循环链表),O(1);

插入元素:

  • 顺序表,空间不够需扩容,扩容有一定性能消耗,还可能有空间浪费;
  • 链表,无扩容概念,按需申请;

应用场景:

  • 顺序表,元素高效存储,频繁访问;
  • 链表,任意位置频繁插入和删除;

缓存利用率

  • 顺序表,缓存利用率高;
  • 链表,缓存利用率低;

备注

  • 存储体系结构及局部原理;
  • cpu访问内存时,会读取一段数据到缓存中;

拓展:与程序员相关的CPU缓存知识;

?

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:56:46  更:2021-08-23 16:59:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:59:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码