Lesson3--顺序表_链表

Lesson3–顺序表和链表

1. 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列.线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表,链表,栈,队列,字符串…

线性表在逻辑上是线性结构,但在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储.

2. 顺序表

2.1 概念及结构

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

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素
    //顺序表的静态存储
    #define N 7
    typedef int SLDataType;
    typedef struct SeqList
    {
     SLDataType array[N];//定长数组
     size_t size;//有效数据的个数
    }SeqList;
    
  2. 动态顺序表:使用动态开辟的数组存储
    //顺序表的动态存储
    typedef struct SeqList
    {
     SLDataType* array;//指向动态开辟的数组
     size_t size;//有效数据个数
     size_t capacity;//容量空间的大小
    }SeqList;
    

2.2 接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致空间开多了浪费,开少了不够用.所以现实中基本都是使用动态顺序表,根据需要动态地分配空间大小.

//顺序表的动态存储
typedef int SLDataType;

//sequence list
typedef struct SeqList
{
 int* array;          //指向动态开辟的数组
 int size;            //有效数据个数
 int capacity;        //空间容量大小
}SL;

//顺序表初始化
void SLInit(SL* psl);
//顺序表销毁时
void SLDestroy(SL* psl);
//顺序表打印
void SLPrint(SL* psl);
//检查空间,如果满了,则扩容
void SLCheckCapacity(SL* psl);
//顺序表尾插
void SLPushBack(SL* psl, SLDataType x);
//顺序表头插
void SLPushFront(SL* psl, SLDataType x);
//顺序表尾删
void SLPopBack(SL* psl);
//顺序表头删
void SLPopFront(SL* psl);
//顺序表pos位置插入
void SLInsert(SL* psl, int pos, SLDataType x);
//顺序表pos位置删除
void SLErase(SL* psl, int pos);
//顺序表查找
int SLFind(SL* psl, SLDataType x);

3. 链表

3.1 链表的概念及结构

概念:链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的.

在这里插入图片描述

注意

  1. 链式结构在逻辑上是连续的,但在物理上不一定连续.
  2. 现实中的节点一般都是从堆上申请出来的.
  3. 从堆上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续.

3.2 链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  1. 单向或双向
    在这里插入图片描述

  2. 带头或不带头
    在这里插入图片描述

  3. 循环或非循环
    在这里插入图片描述

实际中最常用的两种结构:

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据.实际中更多是作为其它数据结构的子结构.
  2. 带头双向循环链表:结构最复杂,一般用在单独存储数据.实际中使用的链表数据结构,都是带头双向循环链表.

3.3 链表的实现

//无头单向非循环链表
typedef int SLNDataType;
typedef struct SListNode
{
	SLNDataType val;
	struct SListNode* next;
}SLNode;
//单链表打印
void SLTPrint(SLNode* phead);
//单链表尾插
void SLTPushBack(SLNode** pphead, SLNDataType x);
//单链表头插
void SLTPushFront(SLNode** pphead, SLNDataType x);
//单链表尾删
void SLTPopBack(SLNode** pphead);
//单链表头删
void SLTPopFront(SLNode** pphead);
//单链表查找
SLNode* SLTFind(SLNode* phead, SLNDataType x);
//在pos前插入
void SLTInsert(SLNode** pphead, SLNode* pos, SLNDataType x);
//在pos后插入
void SLTInsertAfter(SLNode* pos, SLNDataType x);
//删除pos位置后的值
void SLTErase(SLNode** pphead, SLNode* pos);
//单链表销毁
void SLTDestroy(SLNode** pphead);

3.4 双向链表的实现

//带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
 LTDataType _data;
 struct ListNode* next;
 struct ListNode* prev;
}ListNode;
//创建返回链表的头结点.
ListNode* ListCreate();
//双向链表销毁
void ListDestory(ListNode* plist);
//双向链表打印
void ListPrint(ListNode* plist);
//双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);
//双向链表尾删
void ListPopBack(ListNode* plist);
//双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);
//双向链表头删
void ListPopFront(ListNode* plist);
//双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);
//双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
//双向链表删除pos位置的结点
void ListErase(ListNode* pos);

4. 顺序表和链表的区别

不同点顺序表链表
存储空间物理上一定连续逻辑上连续物理上不一定连续
随机访问支持: O ( 1 ) O(1) O(1)不支持: O ( N ) O(N) O(N)
任意位置插入或删除元素可能需要搬移元素,效率低$O(N)只需修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置频繁插入和删除
缓存利用率
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值