线性表的顺序存储和链式存储—Python数据结构(二)

线性表

定义:
线性表的定义是描述其逻辑结构,而通常会在线性表上进行的查找、插入、删除等操作。

线性表作为一种基本的数据结构类型,在计算机存储器中映象(表示)一般有两种形式,一种是顺序映象,一种是链式映象。

线性表的顺序存储

若将线性表L=(a0,a1,…an+1)中的各个元素一次存储于计算机一片连续的存储空间,这种机制表示为线性表的顺序存储结构。

特点:

逻辑上相邻的元素 ai,ai+1,其存储位置也是相邻的;

存储密度高,方便对数据遍历查找。

对表的插入和删除等运算的效率较差。

程序实现

在Python中,list存放于一片单一连续的内存块,故可借助于列表类型来描述线性表的顺序存储结构,而且列表本身就提供了丰富的接口满足这种数据结构的运算。

线性表链式存储

在这里插入图片描述

特点:

  • 逻辑上相邻的元素 ai,ai+1,其存储位置也不一定相邻。

  • 存储稀疏,必须开辟整块存储空间。

  • 对表的插入和删除等运算的效率较高。

  • 逻辑结构复杂。

程序实现:

创建明为link_list.py的脚本,主要用于编写链式结构的线性表,并将其接口也做好封装

#创建节点类
class Node:
  """
  思路:将自定义的类视为节点的生成的类,实例对象中包含数据部分和指向下一个节点的next
  """

  def __init__(self, val, next=None):
      self.val = val
      self.next = next


class LinkList():
  """
  思路:单链表类,生成对象可以进行增删改查操作
  具体操作通过调用具体方法完成。
  """

  def __init__(self):
      """
      初始化链表,标记一个链表的开端,以便于获取后续的节点。
      """
      self.head = Node(None)

  # 通过list_为来拿表添加一组节点
  def init_list(self, list_):
      p = self.head  # p作为移动变量
      for item in list_:
          p.next = Node(item)
          p = p.next

  # 遍历链表
  def show(self):
      p = self.head.next
      while p is not None:
          print(p.val)
          p = p.next  # 向后移动一个

  # 判断链表为空
  def is_empty(self):
      if self.head.next is None:
          return True
      else:
          return False

  # 清空链表
  def clear(self):
      self.head.next = None

  # 尾部插入
  def append(self, val):
      p = self.head
      while p.next is not None:
          p = p.next
      p.next = Node(val)

  # 头部插入
  def head_insert(self, val):
      node = Node(val)
      node.next = self.head.next
      self.head.next = node

  # 插入指定位置
  def insert(self, index, val):
      p = self.head
      for i in range(index):
          if p.next is None:
              break
          p = p.next
      node = Node(val)
      node.next = p.next
      p.next = node

  # 删除节点
  def delete(self, x):
      p = self.head
      while p.next and p.next.val != x:
          p = p.next
      if p.next is None:
          raise ValueError(" x is not in linklist")
      else:
          p.next = p.next.next

  # 获取某个索引的值,传入节点位置,获取节点值
  def get_index(self, index):
      p = self.head.next
      for i in range(index):
          if p.next is None:
              raise IndexError("index out of range")
          p = p.next
      return p.val



测试

from link_list import *
import time

# l = range(999999)
l = [i for i in range(999999)]
# 链表初始化
link = LinkList()
# 链表插入
link.init_list(l)
# 开始计时
tm = time.time()
# for i in l:
#     print(i)  #  3.307s 列表
# link.show()  # 4.61s  单链表
# l.append(8899)  # 列表尾部插入 2.86* 10-6

# link.append(8899)  # 链表尾部插入  0.0534

# l.insert(0, 8899)   # 列表头部插入,0.00392
# link.head_insert(8899)  # 链表头部插入 4.76*10-6
# l.insert(100, 2344)  # 列表插入到指定位置数据, 0.0037
# link.insert(300000, 2344)  # 0.021

# l.remove(200)  # 按照值进行删除 0.0058
# link.delete(850218)  # 按照值进行删除 0.085
# print(l[10])  # 按照索引获取值,1.88
# print(link.get_index(10))  # 按照索引获取值,2.69*10-5
# 计时结束
print("time:", time.time() - tm)

'''
总结:
1. 数据初始化输出,列表的速度最快,即线性表的顺序结构查询速度高。
2. 数据尾部插入,列表速度最快,即线性表的顺序结构。
3. 数据头部插入,链表的插入最快,不需要遍历,列表插入时,需要把后续数据全部重构。
4. 插入到指定指定位置时,只有特殊的头部或尾部才有明显的时间差,其他位置时间差相差不大。
'''

练习题

'''
现有两个有序的列表,请使用单链表方式将其进行合并,合并后的数据仍然是有序数据.
'''
from link_list import *

l1 = LinkList()
l2 = LinkList()

l1.init_list([2, 3, 5, 9, 13, 15])
l2.init_list([1, 4, 6, 7, 8, 10, 11, 12, 14])


def merge(l1, l2):
    p = l1.head
    q = l2.head.next
    while p.next is not None:
        if p.next.val < q.val:
            p = p.next
        else:
            tmp = p.next
            p.next = q
            p = p.next
            q = tmp
    p.next = q


merge(l1, l2)
l1.show()


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值