前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >顺序表与单链表

顺序表与单链表

作者头像
用户3577892
发布2021-02-23 15:10:30
9460
发布2021-02-23 15:10:30
举报
文章被收录于专栏:数据科学CLUB
  • 顺序表
  • Python顺序表中基本操作的实现
    • list其他操作
    • list内置操作的时间复杂度
  • 单链表
  • python单链表基本操作的实现
    • 单个节点实现
    • 单链表的实现
  • 顺序表与单链表的对比

顺序表

线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,这种表示 也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为顺序表(Sequent ial List

)_{\circ}

其特点是, 逻辑上相邻的数据元素,其物理次序也是相邻的。假设线性表的每个元素需占用

l

个存储单元,并以所占的第一个单元的存储地址作为数据元 素的存储起始位置。则线性表中第

i+1

个数据元素的存储位置

\operatorname{LOC}\left(a_{i+1}\right)

和第

i

个数据元素的存 储位置 LOC

\left(a_{i}\right)

之间满足下列关系:

\operatorname{LOC}\left(a_{i+1}\right)=\operatorname{LOC}(a_{i})+l

一般来说,线性表的第

i

个数据元素

a_{i}

的存储位置为:

\operatorname{LOC}(q)=\operatorname{LOC}(q)+(i-1) \times l
代码语言:javascript
复制
a = [1,2,3,4,4,5]

id(a[1])-id(a[0])
代码语言:javascript
复制
32
代码语言:javascript
复制
id(a[2])-id(a[1])
代码语言:javascript
复制
32
代码语言:javascript
复制
id(a[0]) + 32*3 == id(a[3])
代码语言:javascript
复制
True

Python顺序表中基本操作的实现

Python的 list 和 tuple采用了顺序表的实现技术,具有顺序表的所有性质

  1. 初始化

顺序表的初始化操作就是构造一个空的顺序表。

代码语言:javascript
复制
alist = []
  1. 取值

取值操作是根据指定的位置序号i,获取顺序表中第i个数据元素的值。由于顺序存储结构具有随机存取的特点,可以直接通过数组下标定位得到,elem[i-1]单元存储第i个数据元素。

  • 时间复杂度为
\mathrm{O}(1)
代码语言:javascript
复制
a[2]
代码语言:javascript
复制
3
  1. 查找

查找操作是根据指定的元素值e,查找顺序表中第1个与e相等的元素。若查找成功,则返回该元素在表中的位置序号;若查找失败,则返回0。

  • 平均时间复杂度为
\mathrm{O}(n)
代码语言:javascript
复制
a.index(4)
代码语言:javascript
复制
3
  1. 插入

线性表的插入操作是指在表的第

i

个位置插人一个新的数据元素

e

, 使长度为

n

的线性表

\left(a_{1}, \cdots, a_{i-1}, a_{i}, \cdots, a_{n}\right)

变成长度为

n+1

的线性表

\left(a_{1}, \cdots, a_{i-1}, e, a_{i} ;, q\right)

一般情况下,在第

i(1 \leqslant i \leqslant n)

个位置插入一个 元素时,需从最后一个元素即第

n

个元素开始,依次向后移动一个位置,直至第

i

个元素(共

n-i+1

个元素 )。

顺序表插入算法的平均时间复杂度为

\mathrm{O}(n)_{\circ}

Python中有多种方法向表中插入某一元素

代码语言:javascript
复制
a
代码语言:javascript
复制
[1, 2, 3, 4, 4, 5]
代码语言:javascript
复制
# 在列表尾部添加一个对象
# 官方:same as s[len(s):len(s)] = [x]
a.append(0)
a
代码语言:javascript
复制
[1, 2, 3, 4, 4, 5, 0]
代码语言:javascript
复制
# 在列表尾部添加一个序列
# 官方:same as s[len(s):len(s)] = t
a.extend([9])
a
代码语言:javascript
复制
[1, 2, 3, 4, 4, 5, 0, 9]
代码语言:javascript
复制
# 在指定位置插入元素
a.insert(2,8)
a
代码语言:javascript
复制
[1, 2, 8, 3, 4, 4, 5, 0, 9]
代码语言:javascript
复制
a.pop(2)
代码语言:javascript
复制
8
  1. 删除

线性表的删除操作是指将表的第

\mathrm{i}

个元素删去,将长度为

n

的线性表

\left(a_{1}, \cdots, a_{i-1}, a_{i}, a_{i+1}, \cdots, a_{n}\right)

变成长度为

n-1

的线性表

\left(a_{1}, \cdots, a_{i-1}, a_{i+1}, \cdots, a_{n}\right)

一般情况下, 删除第

i(1 \leqslant i \leqslant n)

个元素时需将第

i+1

个至第

n

个元素(共

n-i

个元素 ) 依次向前移动一个位置

(i=n \text { 时无需移动 })_{\circ}
  • 顺序表删除算法的平均时间复杂度为
\mathrm{O}(n)
代码语言:javascript
复制
# 从a中删除a[i]等于x的第一项
a.remove(4)
a
代码语言:javascript
复制
[1, 2, 8, 3, 4, 5, 0, 9]
代码语言:javascript
复制
# 返回i处的元素值,并将其从a中删除
a.pop(-1)
a
代码语言:javascript
复制
[1, 2, 8, 3, 4, 5, 0]

list其他操作

代码语言:javascript
复制
b = [1,2,3,4,4]
len(b)
代码语言:javascript
复制
5
代码语言:javascript
复制
min(b)
代码语言:javascript
复制
1
代码语言:javascript
复制
max(b)
代码语言:javascript
复制
4
代码语言:javascript
复制
b.count(4)
代码语言:javascript
复制
2
代码语言:javascript
复制
5 in b
代码语言:javascript
复制
False
代码语言:javascript
复制
2 in b
代码语言:javascript
复制
True
代码语言:javascript
复制
# 反转
b.reverse()
b
代码语言:javascript
复制
[4, 4, 3, 2, 1]
代码语言:javascript
复制
# 删除某几项
del b[1:3]
b
代码语言:javascript
复制
[4, 2, 1]
代码语言:javascript
复制
# 清空
b.clear()
b
代码语言:javascript
复制
[]

list内置操作的时间复杂度

单链表

线性表链式存储结构的特点是:用一组任意的存储单元存储线性表的数据元素(这组存储单 元可以是连续的,也可以是不连续的

)_{\circ}

因此,为了表示每个数据元素

a_{i}

与其直接后继数据元素

a_{i+1}

之间的逻辑关系,对数据元素

a_{i}

来说,除了存储其本身的信息之外,还需存储一个指示其直 接后继的信息(即直接后继的存储位置

)_{\circ}

这两部分信息组成数据元素

a_{i}

的存储映像,称为结点( node )。它包括两个域:其中存储数据元素信息的域称为数据域; 存储直接后继存储位置的域称 为指针域。指针域中存储的信息称作指针或链。

n

个结点(

a_{i}(1 \leqslant i \leqslant n)

的存储映像 ) 链结成一 个链表,即为线性表

\left(a_{1}, a_{2}, \cdots, a_{n}\right)

示意图

python单链表基本操作的实现

单个节点实现

代码语言:javascript
复制
class LNode(object):
    def __init__(self,elem,next = None):
        self.elem = elem
        self.next = next

单链表的实现

  1. 单链表的初始化
代码语言:javascript
复制
class SingleLinkList(object):
    def __init__(self):
        self.__head = None
#         头结点的指针域置空
  1. 判断链表是否为空
代码语言:javascript
复制
def is_empty(self):
    return self.__head == None
  1. 链表长度
代码语言:javascript
复制
def length(self):
# p初始时指向头节点
    p = self.__head
    count = 0
# 尾节点指向None,当未到达尾部时
    while p != None:
        count += 1
#     将cur后移一个节点
        p = p.next
    return count
  1. 取值

和顺序表不同,链表中逻辑相邻的结点并没有存储在物理相邻的单元中,这样 ,根据给定的 结点位置序号i'在链表中获取该结点的值不能像顺序表那样随机访问,而只能从链表的首元结 点出发,顺着链域 next 逐个结点向下访问。

  • 单链表取值算法的平均时间复杂度为
\mathrm{O}(n)
代码语言:javascript
复制
def get_elem(self,i):
#     p为扫描指针
    p = self.__head
    while p != None and 0<i<self.length():
        i -= 1
        p = p.next
    return p.elem
  1. 查找

链表中按值查找的过程和顺序表类似,从链表的首元结点出发, 依次将结点值和给定值e进 行比较, 返回查找结果。

  • 其平均时间复杂度也为
\mathrm{O}(n)_{\circ}
代码语言:javascript
复制
def loc_elem(self,elem):
    p = self.__head
    while p != None:
        if p.elem == elem:
            return True
        else:
            p = p.next
    return False
  1. 插入

假设要在单链表的两个数据元素a和b之间插入一个数据元素x, 已知p为其单链表存储结 构中指向结点a的指针

步骤:

  1. 查找结点
a_{i-1}

并由指针

p

指向该结点。

  • 生成一个新结点*s。
  • 将新结点*s 的数据域置为 e。
  • 将新结点*s 的指针域指向结点 a
_{i}
  • 将结点p 的指针域指向新结点s。

时间复杂度为

\mathrm{O}(n)
代码语言:javascript
复制
def insert(self, pos, elem):
    node = LNode(elem)
    count = 0
# p用来指向指定位置pos的前一个位置pos-1,初始从头节点开始移动到指定位置
    p = self.__head
    while count < (pos-1):
        count += 1
        p = p.next
# 先将新节点node的next指向插入位置的节点
    node.next = p.next
# 将插入位置的前一个节点的next指向新节点
    p.next = node
  1. 删除

要删除单链表中指定位置的元素,同插人元素一样,首先应该找到该位置的前驱结点。如图所示,在单链表中删除元素b时,应该首先找到其前驱结点a。为了在单链表中实现元素a、b和c之间逻辑关系的变化,仅需修改结点a中的指针域即可。假设p为指向结点a的指针,则修改指针的语句为

p->n e x t=p->n e x t->n e x t
  • 时间复杂度为
\mathrm{O}(n)
代码语言:javascript
复制
# 按值删除
def remove_1(self, elem):
    cur = self.__head
    pre = None
    while cur != None:
        if cur.elem == elem:
#             先判断此结点是否是头节点
#             头节点
            if cur == self.__head:
                self.__head = cur.next
            else:
                pre.next = cur.next
            break
        else:
            pre = cur
            cur = cur.next
            
# 按位置删除

def remove_2(self,i):
    p = self.__head
    count = 0
    while p != None:
        if count != i-1:
            p = p.next     
            count += 1
        else:
            p.next = p.next.next
        break
  1. 创建单链表

  • 头插法

(1) 创建一个只有头结点的空链表。

(2) 根据待创建链表包括的元素个数

n

, 循环

n

次执行以下操作:

  • 生成一个新结点*p;
  • 输入元素值赋给新结点*p 的数据域;
  • 将新结点*p 插人到头结点之后。
  • 尾插法

(1) 创建一个只有头结点的空链表。

(2) 尾指针 r 初始化,指向头结点。

(3) 根据创建链表包括的元素个数

n

, 循环

n

次执行以下操作:

  • 生成一个新结点*p;
  • 输入元素值赋给新结点*p 的数据域;
  • 将新结点p 插入到尾结点r之后;
  • 尾指针 r 指向新的尾结点*p。。
代码语言:javascript
复制
# 头插法
def add(self, elem):
#     先创建一个保存item值的节点
    node = LNode(elem)
#     将新节点的链接域next指向头节点,即__head指向的位置
    node.next = self.__head
#     将链表的头_head指向新节点
    self.__head = node
代码语言:javascript
复制
# 尾插法
def append(self, elem):
    node = LNode(elem)
    # 先判断链表是否为空,若是空链表,则将_head指向新节点
    if self.is_empty():
        self.__head = node
    # 若不为空,则找到尾部,将尾节点的next指向新节点
    else:
        p = self.__head
        while p.next != None:
            p = p.next
        p.next = node

顺序表与单链表的对比

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据科学CLUB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 顺序表
  • Python顺序表中基本操作的实现
    • list其他操作
      • list内置操作的时间复杂度
      • 单链表
      • python单链表基本操作的实现
        • 单个节点实现
          • 单链表的实现
          • 顺序表与单链表的对比
          相关产品与服务
          对象存储
          对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档