线性表
线性表是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。线性表的逻辑结构简单,便于实现和操作。
线性表的特征:
(1)线性表是一个序列
(2)n=0时,线性表是一个空表
(3)线性表中的第一个元素无前驱,最后一个元素无后继,其他元素有且只有一个前驱和后继。
(4)线性表是有长度的,其长度就是元素个数,且线性表的元素个数是有限的。
线性表的分类:
(1)顺序表
(2)链表
顺序表
顺序表是线性表的顺序存储方式,指的是用一组地址连续的存储单元依次存储线性表的数据结构。
顺序表在物理存储方式上表现为一段连续的地址空间,相同数据类型的数据元素被依次放在这个空间中。
一个顺序表需要包含三个属性:(1)存储空间的起始位置;(2)线性表的存储容量;(3)线性表的当前长度
顺序表的基本操作与时间复杂度:
(1)访问 ,存取:O(1)
(2)插入:O(n)
(3)删除:O(n)
操作算法说明:
(1)访问,存取:即获取线性表指定元素的位置。每个数据元素都对应一个存储地址,知道了地址即可一次拿到指定数据。
(2)插入:即在表中的第i个位置插入一个新元素.
(a)如果插入位置不合理(0或大于n),抛出异常
(b)如果线性表长度超出空间容量,抛出异常或动态增加空间容量
(c)从最后一个元素开始向前遍历到第i个位置,分别将它们向后移动一位
(d)将待插入元素填入位置i处
(e)线性表长度加1
(3)删除:即删除表中指定元素。
(a)如果删除的位置不合理(0或大于n),抛出异常
(b)删除第i个位置的元素
(c)从删除元素位置开始向后遍历到最后一个元素,分别将它们向前移动一位
(d)线性表长度减1
总结:顺序表使用存取数据,不适合经常插入和删除数据的应用。
链表(Linked List)
链表是线性表的链式存储方式,是由一组可连续也可不连续的内存结构,通过指针的形式链接在一起的数据类型。
链表共分为3类:(1)单链表 (2)双向链表 (3)循环链表
单链表(Linked List)
单链表的说明:
(1)Data数据+Next指针,组成一个单链表的数据结构。
(2)最后一个数据元素没有直接后继,其Next指针为空(NULL)
(3)单链表可由头指针唯一确定
单链表的基本操作与时间复杂度:
(1)查找,存取:O(n)
(2)插入:O(1)
首先需要从头开始向后遍历,直到找到第i-1个元素(这属于查找的过程),创建新节点,改变指针的指向。
假设待插入结点为s,第i-1个结点为p, s -> next = p -> next; p -> next = s;
(3)删除:O(1)
首先需要从头开始向后遍历,直到找到第i-1个元素(这属于查找的过程),然后改变指针的指向。
假设待删除结点的前一个结点为p,p -> next = p -> next -> next;
双向链表(Double Linked List)
双向链表说明:
(1)Prev指针+Data数据+Next指针,组成一个双向链表
(2)表头的Prev指针为空(NULL),表尾的Next指针为空(NULL)
双向链表的基本操作和时间复杂度:
(1)插入:
假设待插入节点为s,第i-1个结点为p,s -> next = p -> next; p -> next -> prior = s; s -> prior = p; p -> next =s;
(2)删除:
假设待删除结点为p,p -> prior -> next = p -> next; p -> next -> prior = p -> prior; free(p);
循环链表(Circular Linked List)
循环链表说明:
(1)循环链表分为单向循环链表和双向循环链表
(2)单向循环链表就是在单链表的基础上,把表尾的Next指针指向表头,形成一个闭环
(3)双向循环链表就是在双向链表的基础上,把表尾的Next指针指向表头,再把表头的Prev指针指向表尾,形成一个闭环。
(4)循环链表没有表头和表尾的说法
静态链表(Static List)
用数组描述的链表叫做静态链表,这种描述方法叫做游标实现法。是单链表的另一种描述形式:即在没有指针的时候,用数组来替代指针来描述单链表。
游标 | 5 | 2 | 3 | 4 | 0 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ... | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
数据 | A | C | D | E | |||||||||||
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ... | 999 |
解析:上表的静态链表中有两个数组游标和数据,其中数据数组存储数据,游标存储同下标为数据的下一个数据的下标值
(1)先查看下标为999的游标值为1,
(2)根据游标值1找到下标为1的数据A
(3)A对应的游标值为2
(4)根据游标值2找到下标为2的数据C
(5)C对应的游标值为3
(6)根据游标值3找到下标为3的数据D,以此类推
静态链表说明:
(1)Data数据+cur下标(即存储Data下一个元素坐在数组中对应的下标),组成一个静态链表。
(2)下标为0的结点Data区不包含任何数据
(3)数组的最后一个结点的cur存放第一个结点(是指有实质意义的数据的结点)的下标
静态链表操作:
(1)插入:
(a)以上表为例,首先是获得空闲量的下标,即当前数组第一个元素的游标值(cur值)5,就是第一个备用空闲的下标值,然后找到下标值为5的元素对应的游标值6,将数组第一个元素的游标值改为6
(b)在下标值为5的数据单元中放入插入值data,并将其游标值修改为0
(c)若插入值为末位,则直接将下标为4的数据对应的游标改为5,否则循环查找要插入值的上一位,并对应将下标为4的游标值改为5
(2)删除:
(a)首先是找到要删除结点的下标,假如要删除下标为2的元素C,则将C的上一个元素游标值改为3
(b)找到空闲值的游标5,将要删除节点的游标值改为5,将空闲值的游标值改为删除元素的下标值。
链表总结:
(1)单链表可以方便的在链表尾部插入节点,但不支持高效的表尾删除操作。
(2)双向链表相比单链表的优势在于它同时支持高效的正向及反向遍历,并且可以方便的在链表尾部删除结点。
(3)循环链表被视为“无头无尾”,循环链表的无边界使得在这样的链表上设计算法会比普通链表更加容易。
(4)静态链表具有链式存储结构的优点,缺点是不能实现动态分配。
顺序表 vs 链表
存储类别 | 顺序表 | 单链表 |
---|---|---|
存储方式 | 一段连续的存储单元依次存储线性表的数据元素 | 链式存储,用一组任意的存储单元存放线性表的数据元素 |
时间性能 | 查找O(1),插入和删除O(n) | 查找O(n),插入和删除O(1) |
空间性能 | 需要预先分配存储空间,分大了浪费,分小了溢出 | 不需要预分配存储空间,只要有就可以分配,元素个数不受限制 |
(1)若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序表的存储结构;若需要频繁插入和删除,宜采用单链表存储结构。
(2)顺序表使用数组事项, 一组地址连续的存储单元,数组大小有两种方式指定,一是静态分配,而是动态扩展。
(3)顺序表有随机访问特性,存储密度高,逻辑上相邻的元素,无力商业相邻,但是插入删除需要移动大量元素。
(4)链式存储结构允许存储空间不连续,插入删除时不需要移动大量的元素,只需要修改指针即可。但是查找某元素只能从头遍历。