数据结构笔记2:线性表

Table of Contents

线性表定义:

线性表基本操作:

线性表顺序表示:

顺序表定义

顺序表基本操作:

插入

删除

按值查找

线性表链式表示:

单链表定义

扫描二维码关注公众号,回复: 13139275 查看本文章

单链表操作

特殊链表

顺序表与链表比较

三个常用操作:最值、逆置、归并

题目:


线性表定义:

定义:数据元素类型相同,序列(有先后)有限。抽象性,逻辑结构-一对一的相邻关系

除了首尾结点,其他都有前驱后继

线性表基本操作:

  1. InitList(&L)初始化:创建空表(参数为引用类型)
  2. DestroyList(&L)销毁:释放空间
  3. LocateElem(L,e)按值查找
  4. GetElem(L,i)按位查找
  5. ListInser(&L,i,e)插入。默认前插
  6. ListDelete(&L,i,&e)删除。并用e返回删除的值
  7. PrintList(L)输出
  8. Empty(L)判空
  9. Length(L)求表长

线性表顺序表示:

顺序表定义

顺序表:线性表的顺序存储

顺序表常用数组存放,顺序表与数组比较:

开始下标:数组0,顺序表1

容量:数组固定,顺序表可扩增

相似性:可随机存取,可由第一个元素地址直接推算所有元素

推算元素地址:

LOC(A)+(n-1)sizeof(ElemType)

数组的静态分配与数组的动态分配:

动态分配定义时只有一个地址,不直接定义数组,而是在使用时申请initSize个空间

动态分配可以新申请一块空间转移旧数据并扩容,不会溢出。但不是链式存储,还是连续存储空间

顺序表基本操作:

插入、删除、按值查找

插入

注意返回值bool是否插入成功,参数&L表地址(否则局部变量无法作用于原表),参数i为顺序表下标而非数组下标,参数e为需要插入的值

数据合法判断:1<=i<=L.length+1

判断数组是否已满:L.length>=MaxSize

从最后一个元素开始往后挪,将数据保存到线性表

修改线性表长度

时间复杂度:

最好:表尾(length+1)插入O(1)

平均:所有位置等概率。合法位置有n+1个,每个位置的概率为1/(n+1),每个位置循环次数n-i+1。根据等差数列求和公式计算P=Σ(n-i+1)/(n+1)=n/2。同阶无穷大O(n)

最坏:循环n次。O(n)

删除

返回和参数类似,注意参数&e将删除的值传递到函数体外部,所以是引用类型

数据合法判断:1<=i<=L.length

保存要删除的数据元素,从i之后位置挨个往前挪

修改线性表长度

时间复杂度:

最好:表尾(length)删除O(1)

平均:所有位置等概率。合法位置有n个,每个位置的概率为1/n,每个位置循环次数n-i。根据等差数列求和公式计算P=Σ(n-i)/n=(n-1)/2。同阶无穷大O(n)

最坏:循环n-1次。O(n)

按值查找

返回值int为顺序表下标,参数L查找的顺序表,参数e查找的值,不需要修改表,不用引用。

遍历整个表,一旦相同则返回数组下标+1,即线性表的下标。

如果找不到,返回0

时间复杂度:

最好:第一个位置(length)直接返回O(1)

平均:所有位置等概率。合法位置有n个,每个位置的概率为1/n,查找到该位置遍历个数n-i。根据等差数列求和公式计算P=Σ(n-i)/n=(n-1)/2。同阶无穷大O(n)

最坏:遍历n个。O(n)

线性表链式表示:

单链表定义

存储单元不一定连续,通过指针实现逻辑关系(顺序表通过物理位置的相邻)

通过Lnode结构体实现,包括data和*next

一个结点指9488可以表示一个单链表(可以找到所有后继)

单链表的缺点:指针域消耗空间,不能随机存取,只能顺序存取(遍历)

单链表具有头指针

头指针常指向头结点,其中头结点数据域不存放信息,可以存放表长

两种单链表表长判定的方法:

引入头结点的优点:统一头结点和其他位置操作、空表和非空表操作

如-在表头插入时前面同样有结点

单链表操作

指针维护逻辑关系

七大操作:头插、尾插、按值查找、按序号查找、删除、求表长

头插

每一次插入在表头进行:s->next=L->next;L->next=s

先输入值判定,再开辟新空间。

时间复杂度O(n)

尾插

找到最后一个指针r

r->next=s;r=s

初始化头结点,s、r指针分别指向插入结点和尾结点(如果不创立尾指针,每次插入都要循环单链表)

初始化需要插入的结点,修改指针,读入下一个结点

结束后尾结点的next指向空

时间复杂度O(n)

按序号查找

需要额外变量记录当前结点编号,从头结点后第一个结点开始count=1

返回值为结点指针

建立工作指针

判断序号合法

判断是否到达表尾部,遍历到序号i

返回结点

时间复杂度:O(n)

按值查找

遍历对比数据元素

返回值为结点指针,参数为链表、需要查找的值

初始化工作指针,遍历查找

循环条件:遍历未完成,数据不等于查找值

返回结点

时间复杂度:O(n)

插入结点

需要知道前一个结点的位置(按序号查找),修改指针。

指针一定要先对新结点保存,再对老结点修改,否则会丢失。

(比头插法多了查找前一个结点位置的过程)

引入头结点进行了插入操作的统一

没有头结点时:

前插法与后插法区别:

前插法找i-1号结点,后插法找第i号。如果只知i号的位置,前插法依旧需要遍历找i-1

后插法实现前插:插入后交换i与s号的数据元素(交换时指针不变,就不用遍历找i-1)

按序号删除结点

找到i-1号的位置

删除第i号,保存该结点

修改i-1号的指针,释放结点

按地址删除结点

先交换数据元素,再删除下一个结点(省去遍历,O(1))

求表长

和按序号查找相似

遍历计算结点数量(不算头结点)

引入头结点优点2:非空表与空表操作统一

带有头结点:也是判断next是否空

无头结点只有头指针:判断头指针是否空(在求表长前需要额外判断)

特殊链表

双链表:

前驱后缀指针都保存,结点3个域:

Prior

Data

Next

修改时两边指针都要考虑,先添加新结点的指针域内容,再修改链表中老指针

表尾与表头表中操作不同

循环链表

静态链表

顺序表与链表比较

存取方式:顺序表可以随机存取,单链表只能顺序存取

逻辑结构、物理结构:单链表逻辑相邻物理不一定相邻,通过指针表示逻辑关系

插入删除:顺序表O(n)移动大量元素,单链表结点未知O(n)但操作只需修改指针

查找:无序按值查找都O(n),按序号查找顺序表O(1)

内存空间:顺序存储需要预先分配,链式存储需要时分配但指针需要额外空间

三个常用操作:最值、逆置、归并

最值:顺序表、链表都需要遍历,O(n)

逆置:

顺序表O(n)

元素个数的奇偶影响结束条件:

奇数个:i=j

偶数个:j>i(j永远不可能=i)

单链表O(n)

指针无法从后向前移动

标记原表尾r,把第一个元素依次插入到r后

结束条件:r变成了第一个

合并:

顺序表O(n)更常用

申请空间size1+size2

元素递增排列,第一个标记分别为两个数组的最小值

其中一个移动完后,另一个直接遍历全部搬入

链表O(n)

也是循环比较,修改指针,但不用新空间

题目:

7.操作:交换位置3和4的元素,顺序表比链表效率高,因为交换首先需要按下标查找。

10.代码不熟练时写成结构体定义,伪代码,复杂处文字公式表达也可拿分

11.

12.注意顺序表的重复值连续,不用从头搜索。可分存储指针、工作指针

12.归并思想

最优法:二分折半

猜你喜欢

转载自blog.csdn.net/lagoon_lala/article/details/108730494
今日推荐