数据结构笔记——顺序表

本文详细介绍了线性表的逻辑结构、顺序存储结构(顺序表)和链式存储结构(包括单链表、循环链表、双链表),探讨了各种结构的实现、操作和特点。顺序表支持随机访问但插入删除操作不便,链式存储则能灵活处理动态变化的线性表。

写在前面

这篇文章以概念和思路为主,大部分实现代码在具体作业中记录。

主要内容

线性表的逻辑结构
线性表的顺序存储结构及实现
线性表的链式存储结构及实现
顺序表和单链表的比较
线性表的其他存储方法

线性表的逻辑结构

线性表( Linear List )的定义
是零个或多个具有相同类型的数据元素的有限序列。
数据元素的个数定义为线性表的 长度 。长度等于零时称为空表,一个非空表通常记为    
L = ( a 1 , a 2 ,……, a n )
其中, a i ( 1 ≤ i ≤ n )称为数据元素,
下标 i 表示该元素在线性表中的位置或序号, 称元素a i位于表的第i个位置,或称a i是表中的第i个元素。

线性表的抽象数据类型定义
ADT List
Data

线性表中的数据元素具有相同类型,相邻元素具有前驱和后继关系
Operation
InitList

前置条件:线性表不存在
输入:无
功能:线性表的初始化
输出: 无
后置条件:一个空的线性表

DestroyList
前置条件:线性表已存在
输入:无
功能:销毁线性表
输出:无
后置条件:释放线性表所占用的存储空间

Length
前置条件:线性表已存在
输入:无
功能:求线性表的长度
输出: 线性表中数据元素的个数
后置条件:线性表不变

Get
前置条件:线性表已存在
输入:元素的序号 i
功能:在线性表中取序号为 i 的数据元素
输出:如果序号合法,返回序号为 i 的元素值,否则抛出异常
后置条件:线性表不变

Locate
前置条件:线性表已存在
输入:数据元素 x
功能:在线性表中查找值等于 x 的元素
输出:如果查找成功,返回元素 x 在表中的序号,否则返回 0
后置条件:线性表不变

Insert
前置条件:线性表已存在
输入:插入位置 i ;待插元素 x
功能:在线性表的第 i 个位置处插入一个新元素 x
输出:若插入不成功,抛出异常
后置条件:若插入成功,表中增加了一个新元素

Delete
前置条件:线性表已存在
输入:删除位置 i
功能:删除线性表中的第 i 个元素
输出:若删除成功,返回被删元素,否则抛出异常
后置条件:若删除成功,表中减少了一个元素

Empty
前置条件:线性表已存在
输入:无
功能:判断线性表是否为空表
输出:若是空表,返回 1 ,否则返回 0
后置条件:线性表不变

PrintList
前置条件:线性表已存在
输入:无
功能:按位置的先后次序依次输出线性表中的元素
输出:线性表的各个数据元素
后置条件:线性表不变

线性表的顺序存储结构及其实现

线性表的顺序存储结构-顺序表

特点:线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素,
作用:线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。
顺序存储的实现:一维数组存储顺序表中的数据

顺序表的实现

const int Maxsize=100;
template <class T>
class SeqList{ 
 private: 
  T data[MaxSize]; // 存放数据元素的数组 
  int length; // 线性表的长度 
 public: 
  SeqList ( ) ;// 无参构造函数   
  SeqList ( T a[ ], int n ) ; // 有参构造函数 
  ~SeqList( ) { } // 析构函数为空 
  int Length ( ) {return length;} // 求线性表的长度 
  T Get ( int i ); // 按位查找,取线性表的第 i 个元素 
  int Locate ( T x ) ; // 按值查找,求线性表中值为 x 的元素序号 
  void Insert ( int i, T x ) ; // 在线性表中第 i 个位置插入值为 x 的元素 
  T Delete ( int i ) ; // 删除线性表的第 i 个元素 
  void PrintList ( ) ; // 遍历线性表,按序号依次输出各元素 
};

构造函数

定义了两个构造函数:

无参构造函数(构造一个空的顺序表)
SeqList ( ) {length=0;}
构造一个非空的顺序表
SeqList ( T a[ ], int n ) ; // 有参构造函数

有参构造函数的实现:
将长度为n的一维数组中的元素依次传入到data中。
在这里插入图片描述

插入操作

1 如果顺序表已满,抛出上溢异常
2 如果元素插入位置不存在,抛出位置异常
3 将最后一个元素至第i个元素(i为插入位置)向后移动一个位置
4 将元素插入到i位置
5 将顺序表的长度增1

插入算法的复杂性分析

问题规模:n
最好情况:在最后插入,不需要移动元素,时间复杂性为O(1);
最坏情况:在开头插入,需要移动n个数据,O(n)
平均时间复杂度:
元素总个数为n,各个位置插入的概率相等为p=1/(n+1 )
平均移动元素次数为
在这里插入图片描述
时间复杂性为O(n)

顺序表中的查找操作

两种查找方法
位置查找,即查找指定位置上的元素
查找,即查找指定的值在顺序表中的位置

顺序表的特点

线性表顺序表示的优点:
(1) 无需为表示结点间的逻辑关系而增加额外的存储空间(因为逻辑上相邻的元素其存储的物理位置也是相邻的);
(2) 可方便地随机存取表中的任一元素。

线性表顺序表示的缺点
(1)插入或删除运算不方便
除表尾的位置外,在表的其它位置上进行插入或删除操作都必须移动大量的结点,其效率较低;
(2)由于顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配,因此当表长变化较大时,难以确定合适的存储规模

线性表的链式存储结构及实现

链式存储分配的特点:
根据线性表的长度动态的申请存储空间,以解决顺序存储中存在的存储空间难以确定的问题。

链式存储结构的实现
单链表
双向链表
循环链表

指针变量的特点
变量的三要素:
名字,内存地址,值

变量的=左值,右值=:
左值指变量的内存地址
右值:

在赋值表达式中,赋值号左边需要左值,右边需要右值;如a=a+100

指针变量
指针变量的右值本身又是一个左值

带头节点的单链表
头结点:如果链表有头节点,则链式结构中的第一个节点称为头结点:其数据域可以存储一些附加信息,如链表长度;其指针域指向链表中的第一个节点。

单链表的实现

单链表的构造-头插法

在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述

单链表的构造-尾插法

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

按位置查找

在这里插入图片描述
查找算法:
1 工作指针P初始化,计数器初始化
2 执行下列操作,直到p为空或指向第i个节点
2.1 工作指针后移
2.2 计数器增1
3 若p为空,则第i个元素不存在,抛出位置异常;否则查找成功,返回节点p的数据元素

单链表的插入操作(按位置进行插入)

在这里插入图片描述在这里插入图片描述
1 工作指针p初始化,计数器初始化
2 查找第i-1个节点,并使工作指针p指向该节点
3 若查找不成功(P==NULL),说明位置错误,抛出位置异常,否则
3.1 生成一个元素值为x的新节点s
3.2 将s插入到p之后

删除算法

在这里插入图片描述

线性表的其他存储方法

循环链表
双向链表
静态链表

循环链表

单链表或者双链表的头尾结点链接起来,就是一个循环链表。
不增加额外存储花销,却给不少操作带来了方便
从循环表中任一结点出发,都能访问到表中其他结点。
在这里插入图片描述
特点:
首尾相接的链表。
可以从任一节点出发,访问链表中的所有节点。
判断循环链表中尾结点的特点:
q->next
== first.

循环链表的几个问题
空表的构造
非空表的构造
循环链表的遍历
按位置查找节点
循环链表的析构

带尾指针的循环链表
在这里插入图片描述

双链表

单链表的主要不足之处是:
link字段仅仅指向后继结点,不能有效地找到前驱
双链表弥补了上述不足之处
增加一个指向前驱的指针
在这里插入图片描述
双链表的结点结构
在这里插入图片描述
双向链表P之后插人节点(p存在后继结点)
处理原则:先处理每个方向的 远端指针,再处理近端指针
在这里插入图片描述

q->rlink=p->rlink;
P->rlink=q;
q->llink=p;
if(q->rlink)
	   q->rlink->llink=q;

双向链表的删除操作
算法描述:
在这里插入图片描述

静态链表

静态链表同样可以借助一维数组来描述:

define  Maxsize= 链表可能达到的最大长度
template<class T>
 struct Node{
       ElemType data; 
       int  next; 
};

在这里插入图片描述
静态链表的特点
优点:
插入和删除时不需要移动元素,直接修改指针即可,因此效率较高
缺点:
静态链表是借助于数组实现的,因此,不能动态的修改数组的大小,存在着跟静态数组一样不能按需进行存储空间的分配

线性表的顺序存储的优点:支持随机访问
线性表的链式存储的优点:插入和删除数据时不需要移动数据
间接寻址:将指针和数组结合起来的一种方法,它将数组中的存储数据元素的单元改为存储指向该元素的指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值